gpt4 book ai didi

cookies - 如何使用带有 OpenId Connect 的刷新 token 在 asp.net 核心中处理过期的访问 token

转载 作者:行者123 更新时间:2023-12-04 00:46:32 32 4
gpt4 key购买 nike

我已经使用“Microsoft.AspNetCore.Authentication.OpenIdConnect”配置了一个 ASOS OpenIdConnect 服务器和一个使用“Microsoft.AspNetCore.Authentication.OpenIdConnect”的 asp.net core mvc 应用程序:“1.0.0”和“Microsoft.AspNetCore.Authentication.Cookies”:“1.0.0”。我已经测试了“授权码”工作流程,一切正常。

客户端 Web 应用程序按预期处理身份验证并创建一个存储 id_token、access_token 和 refresh_token 的 cookie。

如何强制 Microsoft.AspNetCore.Authentication.OpenIdConnect 在过期时请求新的 access_token?

asp.net core mvc 应用忽略过期的 access_token。

我想让 openidconnect 查看过期的 access_token,然后使用刷新 token 进行调用以获取新的 access_token。它还应该更新 cookie 值。如果刷新 token 请求失败,我希望 openidconnect “退出” cookie(删除它或其他东西)。

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
AuthenticationScheme = "Cookies"
});

app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
ClientId = "myClient",
ClientSecret = "secret_secret_secret",
PostLogoutRedirectUri = "http://localhost:27933/",
RequireHttpsMetadata = false,
GetClaimsFromUserInfoEndpoint = true,
SaveTokens = true,
ResponseType = OpenIdConnectResponseType.Code,
AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet,
Authority = http://localhost:27933,
MetadataAddress = "http://localhost:27933/connect/config",
Scope = { "email", "roles", "offline_access" },
});

最佳答案

您必须通过在 startup.cs 中设置来启用 refresh_token 的生成:

  • 将值设置为 AuthorizationEndpointPath = "/connect/authorize";//需要刷新 token
  • 将值设置为 TokenEndpointPath = "/connect/token";//标准 token 端点名称

  • 在您的 token 提供程序中,在 HandleTokenrequest 方法末尾验证 token 请求之前,请确保您已设置离线范围:
            // Call SetScopes with the list of scopes you want to grant
    // (specify offline_access to issue a refresh token).
    ticket.SetScopes(
    OpenIdConnectConstants.Scopes.Profile,
    OpenIdConnectConstants.Scopes.OfflineAccess);

    如果设置正确,当您使用密码 grant_type 登录时,您应该会收到一个 refresh_token。

    然后,您必须从您的客户发出以下请求(我正在使用 Aurelia):
    refreshToken() {
    let baseUrl = yourbaseUrl;

    let data = "client_id=" + this.appState.clientId
    + "&grant_type=refresh_token"
    + "&refresh_token=myRefreshToken";

    return this.http.fetch(baseUrl + 'connect/token', {
    method: 'post',
    body : data,
    headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Accept': 'application/json'
    }
    });
    }

    就是这样,请确保您在 HandleRequestToken 中的身份验证提供程序没有试图操纵类型为 refresh_token 的请求:
        public override async Task HandleTokenRequest(HandleTokenRequestContext context)
    {
    if (context.Request.IsPasswordGrantType())
    {
    // Password type request processing only
    // code that shall not touch any refresh_token request
    }
    else if(!context.Request.IsRefreshTokenGrantType())
    {
    context.Reject(
    error: OpenIdConnectConstants.Errors.InvalidGrant,
    description: "Invalid grant type.");
    return;
    }

    return;
    }

    refresh_token 应该能够通过这个方法,并由另一个处理 refresh_token 的中间件处理。

    如果您想更深入地了解身份验证服务器在做什么,可以查看 OpenIdConnectServerHandler 的代码:

    https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/blob/master/src/AspNet.Security.OpenIdConnect.Server/OpenIdConnectServerHandler.Exchange.cs

    在客户端,您还必须能够处理 token 的自动刷新,这是 Angular 1.X 的 http 拦截器示例,其中一个处理 401 响应,刷新 token ,然后重试请求:
    'use strict';
    app.factory('authInterceptorService',
    ['$q', '$injector', '$location', 'localStorageService',
    function ($q, $injector, $location, localStorageService) {

    var authInterceptorServiceFactory = {};
    var $http;

    var _request = function (config) {

    config.headers = config.headers || {};

    var authData = localStorageService.get('authorizationData');
    if (authData) {
    config.headers.Authorization = 'Bearer ' + authData.token;
    }

    return config;
    };

    var _responseError = function (rejection) {
    var deferred = $q.defer();
    if (rejection.status === 401) {
    var authService = $injector.get('authService');
    console.log("calling authService.refreshToken()");
    authService.refreshToken().then(function (response) {
    console.log("token refreshed, retrying to connect");
    _retryHttpRequest(rejection.config, deferred);
    }, function () {
    console.log("that didn't work, logging out.");
    authService.logOut();

    $location.path('/login');
    deferred.reject(rejection);
    });
    } else {
    deferred.reject(rejection);
    }
    return deferred.promise;
    };

    var _retryHttpRequest = function (config, deferred) {
    console.log('autorefresh');
    $http = $http || $injector.get('$http');
    $http(config).then(function (response) {
    deferred.resolve(response);
    },
    function (response) {
    deferred.reject(response);
    });
    }

    authInterceptorServiceFactory.request = _request;
    authInterceptorServiceFactory.responseError = _responseError;
    authInterceptorServiceFactory.retryHttpRequest = _retryHttpRequest;

    return authInterceptorServiceFactory;
    }]);

    这是我刚刚为 Aurelia 做的一个示例,这次我将我的 http 客户端包装到一个 http 处理程序中,该处理程序检查 token 是否过期。如果它已过期,它将首先刷新 token ,然后执行请求。它使用 promise 来保持与客户端数据服务的接口(interface)一致。此处理程序公开与 aurelia-fetch 客户端相同的接口(interface)。
    import {inject} from 'aurelia-framework';
    import {HttpClient} from 'aurelia-fetch-client';
    import {AuthService} from './authService';

    @inject(HttpClient, AuthService)
    export class HttpHandler {

    constructor(httpClient, authService) {
    this.http = httpClient;
    this.authService = authService;
    }

    fetch(url, options){
    let _this = this;
    if(this.authService.tokenExpired()){
    console.log("token expired");
    return new Promise(
    function(resolve, reject) {
    console.log("refreshing");
    _this.authService.refreshToken()
    .then(
    function (response) {
    console.log("token refreshed");
    _this.http.fetch(url, options).then(
    function (success) {
    console.log("call success", url);
    resolve(success);
    },
    function (error) {
    console.log("call failed", url);
    reject(error);
    });
    }, function (error) {
    console.log("token refresh failed");
    reject(error);
    });
    }
    );
    }
    else {
    // token is not expired, we return the promise from the fetch client
    return this.http.fetch(url, options);
    }
    }
    }

    对于 jquery,您可以查看 jquery oAuth:

    https://github.com/esbenp/jquery-oauth

    希望这可以帮助。

    关于cookies - 如何使用带有 OpenId Connect 的刷新 token 在 asp.net 核心中处理过期的访问 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40032851/

    32 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com