it-swarm.com.de

Wie speichert man das Zugriffstoken? (Oauth 2, Auth-Code-Fluss)

Von dem, was ich verstehe, ist der Zweck des Authorization Code-Flusses der Austausch des Auth-Codes für das Zugriffstoken. Dieser Austausch findet zwischen dem Server, der die Seite und dem Berechtigungsserver bereitstellt, statt, sodass das tatsächliche Zugriffstoken dem Clientbenutzer nicht angezeigt wird.

Wie sollte der Seitenserver das Zugriffstoken speichern, sobald es erhalten wurde? Ich habe aus einem Pluralsight-Beispiel gelernt, in dem es folgenden Codeteil gibt:

    public static HttpClient GetClient()
    {
        HttpClient client = new HttpClient();
        var accessToken = RequestAccessTokenAuthorizationCode();
        client.SetBearerToken(accessToken);

        client.BaseAddress = new Uri(IdentityConstants.API);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));

        return client;
    }

    private static string RequestAccessTokenAuthorizationCode()
    {
        // did we store the token before?
        var cookie = HttpContext.Current.Request.Cookies.Get("ClientMVCCookie.AuthCode");
        if (cookie != null && cookie["access_token"] != null && !string.IsNullOrEmpty(cookie["access_token"]))
        {
            return cookie["access_token"];
        }

        // no token found - request one

        // we'll pass through the URI we want to return to as state
        var state = HttpContext.Current.Request.Url.OriginalString;

        var authorizeRequest = new IdentityModel.Client.AuthorizeRequest(
            IdentityConstants.AuthEndoint);

        var url = authorizeRequest.CreateAuthorizeUrl(IdentityConstants.MVCClientSecret, "code", "management secret",
            IdentityConstants.MVCAuthCodeCallback, state);

        HttpContext.Current.Response.Redirect(url);

        return null;
    }
}

Dies führt dazu, dass jede Anfrage überprüft, ob ein Zugriffstoken im Cookie gespeichert ist. Wenn nicht, wird der Fluss gestartet. Der Rückruf sieht so aus:

public class CallbackController : Controller
{
    // GET: STSCallback
    public async Task<ActionResult> Index()
    {
        // get the authorization code from the query string
        var authCode = Request.QueryString["code"];

        // with the auth code, we can request an access token.
        var client = new TokenClient(
            IdentityConstants.TokenEndoint,
            "mvc_client_auth_code",
             IdentityConstants.MVCClientSecretAuthCode);

        var tokenResponse = await client.RequestAuthorizationCodeAsync(
            authCode,
            IdentityConstants.MVCAuthCodeCallback);

        // we save the token in a cookie for use later on
        var cookie = Response.Cookies["ClientMVCCookie.AuthCode"];
        cookie.Expires = DateTime.Now.AddMinutes(1);
        cookie["access_token"] = tokenResponse.AccessToken;

        // get the state (uri to return to)
        var state = Request.QueryString["state"];

        // redirect to the URI saved in state
        return Redirect(state);
    }
}

Verweigert das Speichern des Zugriffstokens im Cookie nicht den gesamten Zweck des Autorisierungscode-Flusses? Das Cookie wird an den Client-Browser übermittelt und somit dem Client angezeigt. Verpasse ich etwas Dies ist nicht der richtige Weg, um das Token zu speichern. Wie sollte es gespeichert werden?

7
BodzioSamolot

Der Client ist in der OAuth-Terminologie die Komponente, die Anforderungen an den Ressourcenserver stellt. In Ihrem Fall ist der Client der Server einer Webanwendung (NICHT der Browser).

Daher sollte das Zugriffstoken nur auf dem Webanwendungsserver gespeichert werden. Es sollte nicht für den Browser verfügbar gemacht werden und muss dies auch nicht, da der Browser keine direkten Anforderungen an den Ressourcenserver stellt. Es spricht stattdessen mit dem Webanwendungsserver, der wiederum mithilfe des Zugriffstokens Anforderungen an den Ressourcenserver sendet.

Wie sich der Browser beim Webanwendungsserver authentifiziert, hat mit OAuth 2.0 nichts zu tun. Beispielsweise kann es sich um ein reguläres Sitzungscookie handeln, und der Webanwendungsserver ordnet möglicherweise jeder Sitzung oder jedem Benutzer ein Zugriffstoken zu.

Die Token-Anforderung, die den Authentifizierungscode gegen ein Zugriffstoken austauscht, wird vom Webanwendungsserver ausgeführt, und der Webanwendungsserver sollte sich beim Autorisierungsserver authentifizieren (z. B. unter Verwendung eines gemeinsam genutzten client_secret).

Der Autorisierungscodefluss stellt sicher, dass der Client authentifiziert werden kann. Dies schützt vor böswilligen Clients, die sich als legitime Clients erweisen. Nicht alle Webanwendungsclients verfügen über eine Serverkomponente. In einigen Fällen werden Anforderungen an den Ressourcenserver direkt durch JavaScript-Code im Browser gestellt. In solchen Situationen ist der Browser der Client, und das Zugriffstoken muss vom Browser gespeichert werden (in einer JavaScript-Variablen, einem lokalen Speicher oder einem Cookie). In diesem Fall kann der Client nicht authentifiziert werden (durch Verwendung von TLS und dem Server, der nur auf registrierte Endpunkt-URLs umleitet, kann jedoch eine angemessene Sicherheit erreicht werden).

Empfohlene Lektüre zur Sicherheit in OAuth 2.0: https://tools.ietf.org/html/rfc6819#section-4.3.3 (RFC 6819)

14
Florian Winter

Der Cookie ist niemals dem Browser ausgesetzt. Es ist Teil der Antwort, die vom Autorisierungsserver an den Client gesendet wird, der selbst ein Server und kein Browser ist. Die Variable CallbackController, die den Umleitungsendpunkt implementiert, extrahiert das Cookie aus der Antwort.

Der Cookie wird niemals an den Browser weitergeleitet. Wie der Browser sich beim Anwendungsserver des Clients authentifiziert, wird in Ihrem Beispielcode nicht angezeigt und ist nicht Teil von OAuth.

Der Autorisierungsserver könnte das Token im Anforderungshauptteil (z. B. im JSON-Format) anstatt in einem Cookie speichern. Dies macht jedoch keinen Unterschied, da der Client die gesamte Antwort trotzdem sehen und verarbeiten kann.

Weitere Informationen finden Sie in meiner anderen Antwort: https://stackoverflow.com/a/44655679/2279059

Randbemerkung: Die CallbackController verwendet state, um eine endgültige URL zu speichern, an die der Browser umgeleitet werden soll. Dies ist kein Standard, aber es funktioniert. state soll jedoch die Umleitungsendpunkte vor CSRF-Angriffen schützen. Die CallbackController validiert state nicht, leitet aber blind zu der angegebenen URL weiter. Wahrscheinlich wurde dieses Detail ausgelassen, weil der Code als Beispiel gedacht war. Es zeigt sich jedoch, dass dieser Code wahrscheinlich nicht vollständig serienreif ist.

2
Florian Winter

Wenn Sie eine Restressource vom Browser anfordern möchten, ist der Fluss, den Sie benötigen, Implicit Grant. Überprüfen Sie dies Auth0 Beitrag zur Entscheidung zwischen den Flows https://auth0.com/docs/api-auth/which-oauth-flow-to-use . Wenn Sie das Zugriffstoken vom Server verwenden möchten, sollten Sie das Authorization code und generiere ein access token jedes mal wenn du es brauchst, access token soll nicht länger als 5 Minuten leben, Sie müssen es nicht speichern

0
Xavier Ramírez