public async Task <IntrospectionResponse> IntrospectTokenAsync(TokenIntrospectionRequest request, CancellationToken cancellationToken = default) { var discovery = await _discoveryCache.GetAsync().ConfigureAwait(false); request.Address = discovery.IntrospectionEndpoint; return(await _httpClient.IntrospectTokenAsync(request, cancellationToken).ConfigureAwait(false)); }
/// <summary> /// Introspects a token /// </summary> /// <param name="token"></param> /// <param name="tokenTypeHint"></param> /// <param name="parameters"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public Task <TokenIntrospectionResponse> Introspect(string token, string tokenTypeHint = null, Parameters parameters = null, CancellationToken cancellationToken = default) { var request = new TokenIntrospectionRequest { Token = token, TokenTypeHint = tokenTypeHint }; ApplyRequestParameters(request, parameters); return(_client().IntrospectTokenAsync(request, cancellationToken)); }
/// <summary> /// Sets request parameters from the options. /// </summary> /// <param name="request">The request.</param> /// <param name="parameters">The parameters.</param> internal void ApplyRequestParameters(TokenIntrospectionRequest request, Parameters parameters) { request.Address = _options.Address; request.ClientId = _options.ClientId; request.ClientSecret = _options.ClientSecret; request.ClientAssertion = _options.ClientAssertion; request.ClientCredentialStyle = _options.ClientCredentialStyle; request.AuthorizationHeaderStyle = _options.AuthorizationHeaderStyle; request.Parameters = new Parameters(_options.Parameters); if (parameters != null) { foreach (var parameter in parameters) { request.Parameters.Add(parameter); } } }
public async Task <bool> ValidateToken(string token) { var request = new TokenIntrospectionRequest { Address = $"{_options.Authority}/connect/introspect", ClientId = _options.ApiName, ClientSecret = _options.ApiSecret, Token = token }; var response = await _client.IntrospectTokenAsync(request); if (response.IsError) { throw new Exception(response.Error); } // You might want to validate the scope here return(response.IsActive); }
public async Task Http_request_should_have_correct_format() { var handler = new NetworkHandler(HttpStatusCode.NotFound, "not found"); var client = new HttpClient(handler); var request = new TokenIntrospectionRequest { Address = Endpoint, Token = "token" }; request.Headers.Add("custom", "custom"); request.Properties.Add("custom", "custom"); var response = await client.IntrospectTokenAsync(request); var httpRequest = handler.Request; httpRequest.Method.Should().Be(HttpMethod.Post); httpRequest.RequestUri.Should().Be(new Uri(Endpoint)); httpRequest.Content.Should().NotBeNull(); var headers = httpRequest.Headers; headers.Count().Should().Be(2); headers.Should().Contain(h => h.Key == "custom" && h.Value.First() == "custom"); var properties = httpRequest.Properties; properties.Count.Should().Be(1); var prop = properties.First(); prop.Key.Should().Be("custom"); ((string)prop.Value).Should().Be("custom"); }
/// <summary> /// Sends an OAuth token introspection request. /// </summary> /// <param name="client">The client.</param> /// <param name="request">The request.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns></returns> public static async Task <TokenIntrospectionResponse> IntrospectTokenAsync(this HttpMessageInvoker client, TokenIntrospectionRequest request, CancellationToken cancellationToken = default) { var clone = request.Clone(); clone.Method = HttpMethod.Post; clone.Parameters.AddRequired(OidcConstants.TokenIntrospectionRequest.Token, request.Token); clone.Parameters.AddOptional(OidcConstants.TokenIntrospectionRequest.TokenTypeHint, request.TokenTypeHint); clone.Prepare(); HttpResponseMessage response; try { response = await client.SendAsync(clone, cancellationToken).ConfigureAwait(); } catch (Exception ex) { return(ProtocolResponse.FromException <TokenIntrospectionResponse>(ex)); } return(await ProtocolResponse.FromHttpResponseAsync <TokenIntrospectionResponse>(response).ConfigureAwait()); }
public async Task Repeating_a_request_should_succeed() { var document = File.ReadAllText(FileName.Create("success_introspection_response.json")); var handler = new NetworkHandler(document, HttpStatusCode.OK); var client = new HttpClient(handler) { BaseAddress = new Uri(Endpoint) }; var request = new TokenIntrospectionRequest { Token = "token" }; var response = await client.IntrospectTokenAsync(request); response.IsError.Should().BeFalse(); response.ErrorType.Should().Be(ResponseErrorType.None); response.HttpStatusCode.Should().Be(HttpStatusCode.OK); response.IsActive.Should().BeTrue(); response.Claims.Should().NotBeEmpty(); var audiences = response.Claims.Where(c => c.Type == "aud").ToList(); audiences.Count().Should().Be(2); audiences.First().Value.Should().Be("https://idsvr4/resources"); audiences.Skip(1).First().Value.Should().Be("api1"); response.Claims.First(c => c.Type == "iss").Value.Should().Be("https://idsvr4"); response.Claims.First(c => c.Type == "nbf").Value.Should().Be("1475824871"); response.Claims.First(c => c.Type == "exp").Value.Should().Be("1475828471"); response.Claims.First(c => c.Type == "client_id").Value.Should().Be("client"); response.Claims.First(c => c.Type == "sub").Value.Should().Be("1"); response.Claims.First(c => c.Type == "auth_time").Value.Should().Be("1475824871"); response.Claims.First(c => c.Type == "idp").Value.Should().Be("local"); response.Claims.First(c => c.Type == "amr").Value.Should().Be("password"); response.Claims.First(c => c.Type == "active").Value.Should().Be("true"); var scopes = response.Claims.Where(c => c.Type == "scope").ToList(); scopes.Count().Should().Be(2); scopes.First().Value.Should().Be("api1"); scopes.First().Issuer.Should().Be("https://idsvr4"); scopes.Skip(1).First().Value.Should().Be("api2"); scopes.Skip(1).First().Issuer.Should().Be("https://idsvr4"); // repeat response = await client.IntrospectTokenAsync(request); response.IsError.Should().BeFalse(); response.ErrorType.Should().Be(ResponseErrorType.None); response.HttpStatusCode.Should().Be(HttpStatusCode.OK); response.IsActive.Should().BeTrue(); response.Claims.Should().NotBeEmpty(); audiences = response.Claims.Where(c => c.Type == "aud").ToList(); audiences.Count().Should().Be(2); audiences.First().Value.Should().Be("https://idsvr4/resources"); audiences.Skip(1).First().Value.Should().Be("api1"); response.Claims.First(c => c.Type == "iss").Value.Should().Be("https://idsvr4"); response.Claims.First(c => c.Type == "nbf").Value.Should().Be("1475824871"); response.Claims.First(c => c.Type == "exp").Value.Should().Be("1475828471"); response.Claims.First(c => c.Type == "client_id").Value.Should().Be("client"); response.Claims.First(c => c.Type == "sub").Value.Should().Be("1"); response.Claims.First(c => c.Type == "auth_time").Value.Should().Be("1475824871"); response.Claims.First(c => c.Type == "idp").Value.Should().Be("local"); response.Claims.First(c => c.Type == "amr").Value.Should().Be("password"); response.Claims.First(c => c.Type == "active").Value.Should().Be("true"); scopes = response.Claims.Where(c => c.Type == "scope").ToList(); scopes.Count().Should().Be(2); scopes.First().Value.Should().Be("api1"); scopes.First().Issuer.Should().Be("https://idsvr4"); scopes.Skip(1).First().Value.Should().Be("api2"); scopes.Skip(1).First().Issuer.Should().Be("https://idsvr4"); }
public override async Task ReceiveAsync(AuthenticationTokenReceiveContext context) { if (_options.EnableValidationResultCache) { var cachedClaims = await _options.ValidationResultCache.GetAsync(context.Token) .ConfigureAwait(false); if (cachedClaims != null) { SetAuthenticationTicket(context, cachedClaims); return; } } IntrospectionResponse response; try { var request = new TokenIntrospectionRequest { Address = this.introspectionEndpoint, Token = context.Token }; if (!string.IsNullOrEmpty(this._options.ClientId)) { request.ClientId = this._options.ClientId; request.ClientSecret = this._options.ClientSecret; } response = await this.httpClient.IntrospectTokenAsync(request) .ConfigureAwait(false); if (response.IsError) { _logger.WriteError("Error returned from introspection endpoint: " + response.Error); return; } if (!response.IsActive) { _logger.WriteVerbose("Inactive token: " + context.Token); return; } } catch (Exception ex) { _logger.WriteError("Exception while contacting introspection endpoint: " + ex.ToString()); return; } var claims = new List <Claim>(); foreach (var claim in response.Claims) { if (!string.Equals(claim.Type, "active", StringComparison.Ordinal)) { claims.Add(new Claim(claim.Type, claim.Value)); } } if (_options.EnableValidationResultCache) { await _options.ValidationResultCache.AddAsync(context.Token, claims) .ConfigureAwait(false); } SetAuthenticationTicket(context, claims); }