asp.net-coreopenid-connectopeniddict

Defer token grant types to OpenIddict built-in handlers


When using only an authorization code flow in OpenIddict library, it is not required to implement a token endpoint, as the library natively handles the exchange of authorization code for access token. But once you implement an additional token grant type, e.g. client credentials, how do you defer the authorization code grant type to the base library rather than re-doing the claims?

For example, the Aridka sample has this:

    [HttpPost("~/connect/token"), IgnoreAntiforgeryToken, Produces("application/json")]
    public async Task<IActionResult> Exchange()
    {
        var request = HttpContext.GetOpenIddictServerRequest();
        if (request.IsClientCredentialsGrantType())
        {
            // <snip> set some claims ...
            return SignIn(new ClaimsPrincipal(identity), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
        }

        if (request.IsAuthorizationCodeGrantType())
        {
            //TODO: how to defer to underlying library in this case?
            return new OkResult();
        }
       
    }

Is there a way to make the authorization code exchange work like before we added .EnableTokenEndpointPassthrough() without re-implementing claims/principal building?

A simple hack is to do this:

        if (request.IsAuthorizationCodeGrantType())
        {
            var result = await HttpContext.AuthenticateAsync( OpenIddictServerAspNetCoreDefaults.AuthenticationScheme );
            return SignIn( result.Principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme );
        }

But, based on all the samples, there seems to be a lot of useful validation being skipped when using that approach.


Solution

  • But, based on all the samples, there seems to be a lot of useful validation being skipped when using that approach.

    There are two types of validation:

    A simple hack is to do this:

    if (request.IsAuthorizationCodeGrantType())
    {
        var result = await HttpContext.AuthenticateAsync( OpenIddictServerAspNetCoreDefaults.AuthenticationScheme );
        return SignIn( result.Principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme );
    }
    

    When you don't use the pass-through mode, this is exactly the logic used by OpenIddict to handle grant_type=authorization_code and grant_type=refresh_token requests: reusing the claims initially stored in the authorization code/refresh token as-is to create new tokens.

    If you don't want to refresh claims or enforce additional checks, just using this snippet is perfectly fine.