Konfiguration des OAuth 2.0‑API‑Zugriffs auf Google‑Dienste

Ein Google Developer Console‑Projekt für API‑Zugriff erstellen

Das Erstellen eines Projekts in der Google Developer Console ist ein wesentlicher Schritt, um auf Google‑APIs zuzugreifen und diese für Ihre Anwendungen zu nutzen. Dieser Vorgang umfasst das Einrichten eines Projekts, das Akzeptieren von Bedingungen, die Verifizierung Ihrer Identität und die Konfiguration von API‑Einstellungen gemäß Ihren Anforderungen. Die folgenden Schritte führen Sie durch den Prozess der Projekterstellung und das Erlangen der erforderlichen Anmeldedaten für Dienste wie Calendar‑ und Contacts‑APIs.

Schritte zum Erstellen eines Projekts in der Google Developer Console

  1. Gehen Sie zur Adresse https://cloud.google.com/console/project und melden Sie sich mit Ihren Gmail‑Anmeldedaten an
todo:image_alt_text
  1. Aktivieren Sie das Kontrollkästchen "Ich habe die Nutzungsbedingungen für die Google Cloud Platform‑Produkte gelesen und stimme ihnen zu." und drücken Sie die Schaltfläche Erstellen
todo:image_alt_text
  1. "SMS‑Bestätigung" wird angefordert. Drücken Sie die Schaltfläche Weiter:
todo:image_alt_text
  1. Geben Sie Ihren Ländernamen und Ihre Handynummer ein. Drücken Sie die Schaltfläche: Verifizierungscode senden
todo:image_alt_text
  1. Geben Sie den auf Ihrem Handy erhaltenen Verifizierungscode ein.
todo:image_alt_text
  1. In der APIs‑&‑Auth‑\‑APIs‑Liste aktivieren Sie den Status der Calendar‑API und der Contacts‑API. Schalten Sie alle anderen aus.
todo:image_alt_text
  1. Unter APIs & Auth → Anmeldedaten drücken Sie die Schaltfläche "CREAET NEW CLIENT ID" im Abschnitt "OAuth". Wählen Sie "Installed application" und "Other" aus den angegebenen Optionen und klicken Sie auf die Schaltfläche "Create Client ID". Notieren Sie hier die Client‑ID und das Client‑Secret, die in den Beispielcodes dieses Abschnitts verwendet werden.
todo:image_alt_text

Sichere Google OAuth 2.0‑Integration

Bei der Arbeit mit Google OAuth 2.0 in Aspose.Email für .NET benötigen Sie die folgenden Klassen:

  • GoogleOAuthHelper‑Klasse – Vereinfacht den Prozess der Authentifizierung eines Google‑Benutzers und das Erlangen der erforderlichen Tokens für die Interaktion mit Google‑APIs wie Calendar, Contacts und Gmail.

  • GoogleUser‑Klasse – Sie dient dazu, die Anmeldeinformationen zu kapseln und zu verwalten, die ein Benutzer benötigt, um sich zu authentifizieren und mit Google‑Diensten zu interagieren, insbesondere APIs, die OAuth‑2.0‑Authentifizierung erfordern, wie Google Calendar.

  • TokenResponse‑Klasse – Sie ist ein Modell, das entwickelt wurde, um die Antwortdaten von einem OAuth‑2.0‑Token‑Endpunkt zu repräsentieren und zu verarbeiten, wobei Zugriffstoken im Austausch für Autorisierung erhalten werden.

In den folgenden Artikeln finden Sie Codebeispiele, die zeigen, wie diese Klassen in einer .NET‑Umgebung verwendet werden, um eine sichere Interaktion mit OAuth‑2.0‑Diensten zu etablieren.

OAuth 2.0‑Authentifizierung mit der GoogleOAuthHelper‑Klasse

Die Klasse kümmert sich um die Erstellung der Autorisierungscode‑URL, die Erzeugung von Code‑Challenges und das Abrufen von Zugriffs‑ und Refresh‑Tokens. Durch die Verwendung von GoogleOAuthHelper, Entwickler können den OAuth‑2.0‑Ablauf optimieren und eine sichere sowie effiziente Kommunikation mit Google‑Diensten gewährleisten. Das folgende Code‑Snippet zeigt, wie die GoogleOAuthHelper Klasse in ein Projekt:

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;

/// <summary>
/// Developer console:
/// https://console.cloud.google.com/projectselector2
/// Documentation:
/// https://developers.google.com/identity/protocols/oauth2/native-app
/// </summary>
internal class GoogleOAuthHelper
{
    public const string AUTHORIZATION_URL = "https://accounts.google.com/o/oauth2/v2/auth";
    public const string TOKEN_REQUEST_URL = "https://oauth2.googleapis.com/token";

    public const string REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob";
    public const string REDIRECT_TYPE = "code";

    public static string codeVerifier;
    public static string codeChallenge;

    public static CodeChallengeMethod codeChallengeMethod = CodeChallengeMethod.S256;

    public const string SCOPE =
        "https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar" + // Calendar
        "+" +
        "https%3A%2F%2Fwww.google.com%2Fm8%2Ffeeds%2F" + // Contacts
        "+" +
        "https%3A%2F%2Fmail.google.com%2F"; // IMAP & SMTP

    static GoogleOAuthHelper()
    {
        CreateCodeVerifier();
        CreateCodeChallenge();
    }

    internal static string CreateCodeVerifier()
    {
        string allowedChars = "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz-._~";

        const int minLength = 43;
        const int maxLength = 128;

        Random random = new Random();
        int length = minLength + random.Next(maxLength - minLength);
        List<char> codeVerifierChars = new List<char>();

        for (int i = 0; i < length; i++)
        {
            int index = random.Next(allowedChars.Length);
            codeVerifierChars.Add(allowedChars[index]);
        }

        return codeVerifier = string.Join("", codeVerifierChars.ToArray());
    }

    internal static string CreateCodeChallenge()
    {
        if (codeChallengeMethod == CodeChallengeMethod.Plain)
            return codeChallenge = codeVerifier;

        byte[] hashValue = null;
        using (SHA256 sha256 = SHA256.Create())
            hashValue = sha256.ComputeHash(Encoding.ASCII.GetBytes(codeVerifier));

        string b64 = Convert.ToBase64String(hashValue);
        b64 = b64.Split('=')[0];
        b64 = b64.Replace('+', '-');
        b64 = b64.Replace('/', '_');

        return codeChallenge = b64;
    }

    internal static string GetAuthorizationCodeUrl(GoogleUser user)
    {
        return GetAuthorizationCodeUrl(user, SCOPE, REDIRECT_URI, REDIRECT_TYPE);
    }

    internal static string GetAuthorizationCodeUrl(
        GoogleUser user, string scope, string redirectUri, string responseType)
    {
        string state = System.Web.HttpUtility.UrlEncode(Guid.NewGuid().ToString());

        string approveUrl = AUTHORIZATION_URL +
            $"?client_id={user.ClientId}&redirect_uri={redirectUri}&response_type={responseType}&scope={scope}&" +
            $"code_challenge={codeChallenge}&code_challenge_method={codeChallengeMethod.ToString()}&" +
            $"state={state}";

        return approveUrl;
    }

    internal static TokenResponse GetAccessTokenByRefreshToken(GoogleUser user)
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(TOKEN_REQUEST_URL);
        request.CookieContainer = new CookieContainer();
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";

        string clientId = System.Web.HttpUtility.UrlEncode(user.ClientId);
        string clientSecret = System.Web.HttpUtility.UrlEncode(user.ClientSecret);
        string refreshToken = System.Web.HttpUtility.UrlEncode(user.RefreshToken);
        string grantType = System.Web.HttpUtility.UrlEncode("refresh_token");

        string encodedParameters = $"client_id={clientId}&client_secret={clientSecret}&refresh_token={refreshToken}&grant_type={grantType}";

        byte[] requestData = Encoding.UTF8.GetBytes(encodedParameters);
        request.ContentLength = requestData.Length;
        if (requestData.Length > 0)
            using (Stream stream = request.GetRequestStream())
                stream.Write(requestData, 0, requestData.Length);

        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        string responseText = null;
        using (TextReader reader = new StreamReader(response.GetResponseStream(), Encoding.ASCII))
            responseText = reader.ReadToEnd();

        TokenResponse tokensResponse = JsonConvert.DeserializeObject<TokenResponse>(responseText);

        return tokensResponse;
    }

    internal static TokenResponse GetAccessTokenByAuthCode(string authorizationCode, GoogleUser user)
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(TOKEN_REQUEST_URL);
        request.CookieContainer = new CookieContainer();
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";

        string clientId = System.Web.HttpUtility.UrlEncode(user.ClientId);
        string clientSecret = System.Web.HttpUtility.UrlEncode(user.ClientSecret);
        string authCode = System.Web.HttpUtility.UrlEncode(authorizationCode);
        string redirectUri = System.Web.HttpUtility.UrlEncode(REDIRECT_URI);
        string grantType = System.Web.HttpUtility.UrlEncode("authorization_code");

        string encodedParameters = $"client_id={clientId}&client_secret={clientSecret}&code={authCode}&code_verifier={codeVerifier}&redirect_uri={redirectUri}&grant_type={grantType}";

        byte[] requestData = Encoding.UTF8.GetBytes(encodedParameters);
        request.ContentLength = requestData.Length;
        if (requestData.Length > 0)
            using (Stream stream = request.GetRequestStream())
                stream.Write(requestData, 0, requestData.Length);

        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        string responseText = null;
        using (TextReader reader = new StreamReader(response.GetResponseStream(), Encoding.ASCII))
            responseText = reader.ReadToEnd();

        TokenResponse tokensResponse = JsonConvert.DeserializeObject<TokenResponse>(responseText);

        return tokensResponse;
    }

    public enum CodeChallengeMethod
    {
        S256,
        Plain
    }
}

Google OAuth Helper sollte wie folgt verwendet werden:

  1. Zuerst muss eine Autorisierungscode‑URL generiert werden.
  2. Öffnen Sie die URL in einem Browser und führen Sie alle Vorgänge aus. Als Ergebnis erhalten Sie einen Autorisierungscode.
  3. Verwenden Sie den Autorisierungscode, um ein Refresh‑Token zu erhalten.
  4. Wenn das Refresh‑Token vorhanden ist, können Sie es zur Abrufung von Zugriffstoken verwenden.
GoogleUser user = new GoogleUser(email, password, clientId, clientSecret);

string authUrl = GoogleOAuthHelper.GetAuthorizationCodeUrl(user);

Console.WriteLine("Go to the following URL and get your authorization code:");
Console.WriteLine(authUrl);
Console.WriteLine();

Console.WriteLine("Enter the authorization code:");
string authorizationCode = Console.ReadLine();
Console.WriteLine();

TokenResponse tokenInfo = GoogleOAuthHelper.GetAccessTokenByAuthCode(authorizationCode, user);
Console.WriteLine("The refresh token has been received:");
Console.WriteLine(tokenInfo.RefreshToken);
Console.WriteLine();

user.RefreshToken = tokenInfo.RefreshToken;
tokenInfo = GoogleOAuthHelper.GetAccessTokenByRefreshToken(user);
Console.WriteLine("The new access token has been received:");
Console.WriteLine(tokenInfo.AccessToken);
Console.WriteLine();

GoogleUser‑Klasse für OAuth 2.0‑Authentifizierung

Das folgende Code‑Snippet zeigt, wie man die GoogleUser Klasse:

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET

public class GoogleUser
{
    public GoogleUser(string email, string password, string clientId, string clientSecret)
        : this(email, password, clientId, clientSecret, null)
    {
    }

    public GoogleUser(string email, string password, string clientId, string clientSecret, string refreshToken)
    {
        Email = email;
        Password = password;
        ClientId = clientId;
        ClientSecret = clientSecret;
        RefreshToken = refreshToken;
    }

    public readonly string Email;
    public readonly string Password;
    public readonly string ClientId;
    public readonly string ClientSecret;

    public string RefreshToken;
}

Authentifizierung mit OAuth 2.0 mittels TokenResponse‑Klasse

Das folgende Code‑Snippet zeigt, wie die TokenResponse Klasse kann implementiert werden:

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET

using Newtonsoft.Json;

public class TokenResponse
{
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "access_token", Required = Required.Default)]
    public string AccessToken { get; set; }

    [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "token_type", Required = Required.Default)]
    public string TokenType { get; set; }

    [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "expires_in", Required = Required.Default)]
    public int ExpiresIn { get; set; }

    [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "refresh_token", Required = Required.Default)]
    public string RefreshToken { get; set; }

    [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "scope", Required = Required.Default)]
    public string Scope { get; set; }
}