Skip to content
This repository has been archived by the owner on Dec 24, 2020. It is now read-only.

Commit

Permalink
Prevent the deserialization methods from being called twice when rece…
Browse files Browse the repository at this point in the history
…iving an introspection or revocation request with a token_type_hint
  • Loading branch information
kevinchalet committed Oct 9, 2017
1 parent d95810b commit c561a34
Show file tree
Hide file tree
Showing 8 changed files with 564 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,42 @@ private async Task<bool> InvokeIntrospectionEndpointAsync()
// See https://tools.ietf.org/html/rfc7662#section-2.1
if (ticket == null)
{
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
// To avoid calling the same deserialization methods twice,
// an additional check is made to exclude the corresponding
// method when an explicit token_type_hint was specified.
switch (request.TokenTypeHint)
{
case OpenIdConnectConstants.TokenTypeHints.AccessToken:
ticket = await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;

case OpenIdConnectConstants.TokenTypeHints.AuthorizationCode:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;

case OpenIdConnectConstants.TokenTypeHints.IdToken:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;

case OpenIdConnectConstants.TokenTypeHints.RefreshToken:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request);
break;

default:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;
}
}

if (ticket == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,42 @@ private async Task<bool> InvokeRevocationEndpointAsync()
// See https://tools.ietf.org/html/rfc7009#section-2.1
if (ticket == null)
{
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
// To avoid calling the same deserialization methods twice,
// an additional check is made to exclude the corresponding
// method when an explicit token_type_hint was specified.
switch (request.TokenTypeHint)
{
case OpenIdConnectConstants.TokenTypeHints.AccessToken:
ticket = await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;

case OpenIdConnectConstants.TokenTypeHints.AuthorizationCode:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;

case OpenIdConnectConstants.TokenTypeHints.IdToken:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;

case OpenIdConnectConstants.TokenTypeHints.RefreshToken:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request);
break;

default:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;
}
}

if (ticket == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,42 @@ private async Task<bool> InvokeIntrospectionEndpointAsync()
// See https://tools.ietf.org/html/rfc7662#section-2.1
if (ticket == null)
{
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
// To avoid calling the same deserialization methods twice,
// an additional check is made to exclude the corresponding
// method when an explicit token_type_hint was specified.
switch (request.TokenTypeHint)
{
case OpenIdConnectConstants.TokenTypeHints.AccessToken:
ticket = await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;

case OpenIdConnectConstants.TokenTypeHints.AuthorizationCode:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;

case OpenIdConnectConstants.TokenTypeHints.IdToken:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;

case OpenIdConnectConstants.TokenTypeHints.RefreshToken:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request);
break;

default:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;
}
}

if (ticket == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,42 @@ private async Task<bool> InvokeRevocationEndpointAsync()
// See https://tools.ietf.org/html/rfc7009#section-2.1
if (ticket == null)
{
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
// To avoid calling the same deserialization methods twice,
// an additional check is made to exclude the corresponding
// method when an explicit token_type_hint was specified.
switch (request.TokenTypeHint)
{
case OpenIdConnectConstants.TokenTypeHints.AccessToken:
ticket = await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;

case OpenIdConnectConstants.TokenTypeHints.AuthorizationCode:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;

case OpenIdConnectConstants.TokenTypeHints.IdToken:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;

case OpenIdConnectConstants.TokenTypeHints.RefreshToken:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request);
break;

default:
ticket = await DeserializeAccessTokenAsync(request.Token, request) ??
await DeserializeAuthorizationCodeAsync(request.Token, request) ??
await DeserializeIdentityTokenAsync(request.Token, request) ??
await DeserializeRefreshTokenAsync(request.Token, request);
break;
}
}

if (ticket == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,69 @@ public async Task InvokeIntrospectionEndpointAsync_InvalidTokenCausesAnError()
Assert.False((bool) response[OpenIdConnectConstants.Parameters.Active]);
}

[Theory]
[InlineData(OpenIdConnectConstants.TokenTypeHints.AccessToken)]
[InlineData(OpenIdConnectConstants.TokenTypeHints.AuthorizationCode)]
[InlineData(OpenIdConnectConstants.TokenTypeHints.IdToken)]
[InlineData(OpenIdConnectConstants.TokenTypeHints.RefreshToken)]
public async Task InvokeIntrospectionEndpointAsync_TokenIsNotDeserializedTwice(string hint)
{
// Arrange
var server = CreateAuthorizationServer(options =>
{
options.Provider.OnDeserializeAccessToken = context =>
{
Assert.False(context.Request.HasProperty(nameof(options.Provider.OnDeserializeAccessToken)));
context.Request.AddProperty(nameof(options.Provider.OnDeserializeAccessToken), new object());
return Task.FromResult(0);
};
options.Provider.OnDeserializeAuthorizationCode = context =>
{
Assert.False(context.Request.HasProperty(nameof(options.Provider.OnDeserializeAuthorizationCode)));
context.Request.AddProperty(nameof(options.Provider.OnDeserializeAuthorizationCode), new object());
return Task.FromResult(0);
};
options.Provider.OnDeserializeIdentityToken = context =>
{
Assert.False(context.Request.HasProperty(nameof(options.Provider.OnDeserializeIdentityToken)));
context.Request.AddProperty(nameof(options.Provider.OnDeserializeIdentityToken), new object());
return Task.FromResult(0);
};
options.Provider.OnDeserializeRefreshToken = context =>
{
Assert.False(context.Request.HasProperty(nameof(options.Provider.OnDeserializeRefreshToken)));
context.Request.AddProperty(nameof(options.Provider.OnDeserializeRefreshToken), new object());
return Task.FromResult(0);
};
options.Provider.OnValidateIntrospectionRequest = context =>
{
context.Skip();
return Task.FromResult(0);
};
});

var client = new OpenIdConnectClient(server.CreateClient());

// Act
var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest
{
Token = "SlAV32hkKG",
TokenTypeHint = hint
});

// Assert
Assert.False((bool) response[OpenIdConnectConstants.Parameters.Active]);
}

[Fact]
public async Task InvokeIntrospectionEndpointAsync_ConfidentialTokenCausesAnErrorWhenValidationIsSkipped()
{
Expand Down
Loading

0 comments on commit c561a34

Please sign in to comment.