Extension Grants¶
OAuth 2.0はpassword、authorization_codeとのようなトークンエンドポイントの標準認可タイプを定義しますrefresh_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オブジェクトは、あなたがにアクセスすることができます:
- 受信トークン要求(よく知られている検証済みの値)とカスタム値(Rawコレクションを介したもの)
- 結果 - エラーまたは成功
- カスタム応答パラメータ
拡張グラントを登録するには、DIに追加します。
builder.AddExtensionGrantValidator<MyExtensionsGrantValidator>();
例:拡張認可を使用する単純な委任¶
次のシナリオを想像してみましょう。フロントエンドクライアントは、インタラクティブなフロー(例えば、ハイブリッドフロー)で取得したトークンを使用して中間層のAPIを呼び出します。この中間層API(API 1)は、対話ユーザーの代わりにバックエンドAPI(API 2)を呼び出す必要があります。
言い換えると、中間層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、委任アクセストークンが含まれます。