Skip to content
This repository has been archived by the owner on Sep 18, 2021. It is now read-only.

Can I convert reference tokens to JWTs? #1725

Closed
rbanks54 opened this issue Aug 14, 2015 · 11 comments
Closed

Can I convert reference tokens to JWTs? #1725

rbanks54 opened this issue Aug 14, 2015 · 11 comments
Labels

Comments

@rbanks54
Copy link

Consider a microservices architecture where I have an API Gateway (aka reverse proxy) sitting between clients and back end APIs.

Clients get reference tokens from IdSrv and pass them to the API Gateway where they are validated by making a call to IdSrv. All well and good.

I then want the API Gateway to make calls against the internal APIs using the JWT version of the token. Since it's internal at that point, I can validate JWTs locally and avoid extra validation calls against the IdSrv. Unfortunately I can't see any way to do that with IdSrv (unless I'm blind).

Is the ability to convert a reference token to a JWT something you're looking to enable in IdSrv, maybe as an optional return from a validation call, or should I just be building JWTs myself?

@brockallen
Copy link
Member

This is like an "act-as" or "on-behalf-of" style token. There's a OAuth2 work in progress spec for this, but in the meantime you can use the reference token as a custom grant type against the token endpoint. You'd then build a custom token validator to allow the exchange of the reference token for a full JWT.

@rbanks54
Copy link
Author

Thanks @brockallen. I didn't realise there was a draft spec for this approach.

Let me ask the obvious question: Any thoughts on implementing the draft spec and keeping IdSrv updated as it progresses? :-)

For reference I found an AAD sample that looks like it'll cover the scenario at https://github.com/AzureADSamples/WebAPI-OnBehalfOf-DotNet. I might have a play with converting that to use IdSrv.

@brockallen
Copy link
Member

We have an open issue and most of it already written (and a PR even I think), but it's slated for 2.1.

@rbanks54
Copy link
Author

@brockallen Sweet! I'll keep an eye out for it.

I love what you, @leastprivilege and others are doing by the way. Keep up the fantastic work!

@philipbjorge
Copy link

@brockallen + @rbanks54 -- Any idea what's the state on this? Is there functionality built into IdentityServer to support this use-case?
Or do I need to go down the custom grant validator route?

@leastprivilege
Copy link
Member

custom grant validator - I think there is also a sample now in the samples repo.

@philipbjorge
Copy link

Thanks @leastprivilege !

@philipbjorge
Copy link

@leastprivilege @brockallen -- I've taken a stab at a custom grant for exchanging reference tokens for JWTs. It seems to be working.
Anything stupid I might be doing?

public class ExchangeReferenceTokenGrantValidator : ICustomGrantValidator
{
    private readonly ITokenHandleStore tokens;

    public ExchangeReferenceTokenGrantValidator(ITokenHandleStore tokenStore)
    {
        tokens = tokenStore;
    }

    public async Task<CustomGrantValidationResult> ValidateAsync(ValidatedTokenRequest request)
    {
        var referenceToken = request.Raw.Get("reference_token");
        if (referenceToken == null)
        {
            return new CustomGrantValidationResult("Missing Reference Token");
        }

        var token = await tokens.GetAsync(referenceToken); // TODO: Do I need to verify if the token is expired or will it return null in that case?
        if (token == null)
        {
            return new CustomGrantValidationResult("Invalid Reference Token");
        }

        // Generate the JWT as if it was for the reference token's client
        request.Client = token.Client;
        request.Client.AccessTokenType = AccessTokenType.Jwt;
        request.Client.AlwaysSendClientClaims = true;
        return new CustomGrantValidationResult(token.SubjectId ?? token.ClientId, GrantType, token.Claims);
    }

    public string GrantType => "exchange_reference_token";
}
new Client
{
    ClientName = "API Gateway",
    ClientId = "api-gateway",
    Enabled = true,
    Flow = Flows.Custom,
    AllowedCustomGrantTypes = new List<string> { "exchange_reference_token" },
    AllowedScopes = new List<string>
    {
        StandardScopes.AllClaims.Name
    },
    ClientSecrets = new List<Secret>
    { 
        new Secret("secretlol".Sha256())
    }
}

P.S. Leaving this in the issue for future travelers...

@leastprivilege
Copy link
Member

You can also take the TokenValidator as a dependency. That validates the token and returns the claims.

— 
cheers
Dominick Baier

On 29 February 2016 at 18:02:32, Philip Bjorge (notifications@github.com) wrote:

@leastprivilege @brockallen -- I've taken a stab at a custom grant for exchanging reference tokens for JWTs. It seems to be working.
Anything stupid I might be doing?

public class ExchangeReferenceTokenGrantValidator : ICustomGrantValidator
{
private readonly ITokenHandleStore tokens;

public ExchangeReferenceTokenGrantValidator(ITokenHandleStore tokenStore)
{
    tokens = tokenStore;
}

public async Task<CustomGrantValidationResult> ValidateAsync(ValidatedTokenRequest request)
{
    var referenceToken = request.Raw.Get("reference_token");
    if (referenceToken == null)
    {
        return new CustomGrantValidationResult("Missing Reference Token");
    }

    var token = await tokens.GetAsync(referenceToken); // TODO: Do I need to verify if the token is expired or will it return null in that case?
    if (token == null)
    {
        return new CustomGrantValidationResult("Invalid Reference Token");
    }

    // Generate the JWT as if it was for the reference token's client
    request.Client = token.Client;
    request.Client.AccessTokenType = AccessTokenType.Jwt;
    request.Client.AlwaysSendClientClaims = true;
    return new CustomGrantValidationResult(token.SubjectId ?? token.ClientId, GrantType, token.Claims);
}

public string GrantType => "exchange_reference_token";

}
new Client
{
ClientName = "API Gateway",
ClientId = "api-gateway",
Enabled = true,
Flow = Flows.Custom,
AllowedCustomGrantTypes = new List { "exchange_reference_token" },
AllowedScopes = new List
{
StandardScopes.AllClaims.Name
},
ClientSecrets = new List
{
new Secret("secretlol".Sha256())
}
}

Reply to this email directly or view it on GitHub.

@aivans
Copy link

aivans commented Jun 9, 2016

This is like an "act-as" or "on-behalf-of" style token. There's a OAuth2 work in progress spec for this, but in the meantime you can use the reference token as a custom grant type against the token endpoint. You'd then build a custom token validator to allow the exchange of the reference token for a full JWT.

Please point to the OAuth2 spec that solves this. I am interested on the current status.

Thank you

@pi3k14
Copy link

pi3k14 commented Jan 6, 2017

https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-06 I would think.

Any plans for implementing that in IdentityServer?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

6 participants