Skip to content
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
Closed

Can I convert reference tokens to JWTs? #1725

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

Comments

@rbanks54
Copy link

@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
Copy link
Member

@brockallen 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.

@rbanks54
Copy link
Author

@rbanks54 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
Copy link
Member

@brockallen 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
Copy link
Author

@rbanks54 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
Copy link

@philipbjorge 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
Copy link
Member

@leastprivilege leastprivilege commented Feb 24, 2016

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

@philipbjorge
Copy link

@philipbjorge philipbjorge commented Feb 24, 2016

Thanks @leastprivilege !

@philipbjorge
Copy link

@philipbjorge 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
Copy link
Member

@leastprivilege 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
Copy link

@aivans 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 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
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
6 participants