扩展授权

OAuth 2.0定义了令牌端点的标准授权类型,例如passwordauthorization_coderefresh_token扩展授权是一种添加对非标准令牌颁发方案(如令牌转换,委派或自定义凭据)的支持的方法。

您可以通过实现IExtensionGrantValidator接口添加对其他授权类型的支持

public interface IExtensionGrantValidator
{
    /// <summary>
    /// Handles the custom grant request.
    /// </summary>
    /// <param name="request">The validation context.</param>
    Task ValidateAsync(ExtensionGrantValidationContext context);

    /// <summary>
    /// Returns the grant type this validator can deal with
    /// </summary>
    /// <value>
    /// The type of the grant.
    /// </value>
    string GrantType { get; }
}

ExtensionGrantValidationContext对象使您可以访问:

要注册扩展授权,请将其添加到DI:

builder.AddExtensionGrantValidator<MyExtensionsGrantValidator>();

示例:使用扩展授权的简单委派

想象一下以下场景 - 前端客户端使用通过交互流(例如混合流)获取的令牌调用中间层API。此中间层API(API 1)现在希望代表交互式用户调用后端API(API 2):

../_images/delegation.png

换句话说,中间层API(API 1)需要包含用户身份的访问令牌,但需要具有后端API(API 2)的范围。

注意

您可能听说过穷人代表团这一术语,前端的访问令牌只是转发到后端。这有一些缺点,例如API 2现在必须接受API 1范围,这将允许用户直接调用API 2此外 - 您可能希望在令牌中添加一些特定于委托的声明,例如,呼叫路径是通过API 1的事实

实施扩展授权

前端会将令牌发送到API 1,现在需要在IdentityServer上使用API 2的新令牌交换此令牌。

在线上,对交换的令牌服务的调用可能如下所示:

POST /connect/token

grant_type=delegation&
scope=api2&
token=...&
client_id=api1.client
client_secret=secret

扩展授权验证程序的工作是通过验证传入令牌并返回表示新令牌的结果来处理该请求:

public class DelegationGrantValidator : IExtensionGrantValidator
{
    private readonly ITokenValidator _validator;

    public DelegationGrantValidator(ITokenValidator validator)
    {
        _validator = validator;
    }

    public string GrantType => "delegation";

    public async Task ValidateAsync(ExtensionGrantValidationContext context)
    {
        var userToken = context.Request.Raw.Get("token");

        if (string.IsNullOrEmpty(userToken))
        {
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
            return;
        }

        var result = await _validator.ValidateAccessTokenAsync(userToken);
        if (result.IsError)
        {
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
            return;
        }

        // get user's identity
        var sub = result.Claims.FirstOrDefault(c => c.Type == "sub").Value;

        context.Result = new GrantValidationResult(sub, GrantType);
        return;
    }
}

不要忘记在DI上注册验证器。

注册委托客户端

您需要在IdentityServer中进行客户端注册,以允许客户端使用此新的扩展授权,例如:

var client = new client
{
    ClientId = "api1.client",
    ClientSecrets = new List<Secret>
    {
        new Secret("secret".Sha256())
    },

    AllowedGrantTypes = { "delegation" },

    AllowedScopes = new List<string>
    {
        "api2"
    }
}

调用令牌端点

在API 1中,您现在可以自己构建HTTP有效内容,或使用IdentityModel帮助程序库:

public async Task<TokenResponse> DelegateAsync(string userToken)
{
    var payload = new
    {
        token = userToken
    };

    // create token client
    var client = new TokenClient(disco.TokenEndpoint, "api1.client", "secret");

    // send custom grant to token endpoint, return response
    return await client.RequestCustomGrantAsync("delegation", "api2", payload);
}

现在TokenResponse.AccessToken将包含委托访问令牌。

nidie.com.cn - 用心与你沟通