This repository has been archived by the owner. It is now read-only.

Can I convert reference tokens to JWTs? #1725

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

Comments

Projects
None yet
6 participants
@rbanks54

rbanks54 commented Aug 14, 2015

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

This comment has been minimized.

Member

brockallen commented Aug 14, 2015

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.

@brockallen brockallen added the question label Aug 14, 2015

@rbanks54

This comment has been minimized.

rbanks54 commented Aug 17, 2015

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

This comment has been minimized.

Member

brockallen commented Aug 17, 2015

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

This comment has been minimized.

rbanks54 commented Aug 18, 2015

@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!

@rbanks54 rbanks54 closed this Aug 18, 2015

@philipbjorge

This comment has been minimized.

philipbjorge commented Feb 24, 2016

@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

This comment has been minimized.

Member

leastprivilege commented Feb 24, 2016

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

@philipbjorge

This comment has been minimized.

philipbjorge commented Feb 24, 2016

Thanks @leastprivilege !

@philipbjorge

This comment has been minimized.

philipbjorge commented Feb 29, 2016

@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

This comment has been minimized.

Member

leastprivilege commented Mar 4, 2016

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

This comment has been minimized.

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

This comment has been minimized.

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.