/// <summary> /// Goes to UserInfo endpoint to retrieve additional claims and add any unique claims to the given identity. /// </summary> /// <param name="message">message that is being processed</param> /// <param name="jwt">The <see cref="JwtSecurityToken"/>.</param> /// <param name="ticket">authentication ticket with claims principal and identities</param> /// <returns>Authentication ticket with identity with additional claims, if any.</returns> protected virtual async Task <AuthenticateResult> GetUserInformationAsync(OpenIdConnectMessage message, JwtSecurityToken jwt, AuthenticationTicket ticket) { var userInfoEndpoint = _configuration?.UserInfoEndpoint; if (string.IsNullOrEmpty(userInfoEndpoint)) { Logger.UserInfoEndpointNotSet(); return(AuthenticateResult.Success(ticket)); } if (string.IsNullOrEmpty(message.AccessToken)) { Logger.AccessTokenNotAvailable(); return(AuthenticateResult.Success(ticket)); } Logger.RetrievingClaims(); var requestMessage = new HttpRequestMessage(HttpMethod.Get, userInfoEndpoint); requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", message.AccessToken); var responseMessage = await Backchannel.SendAsync(requestMessage); responseMessage.EnsureSuccessStatusCode(); var userInfoResponse = await responseMessage.Content.ReadAsStringAsync(); JObject user; var contentType = responseMessage.Content.Headers.ContentType; if (contentType.MediaType.Equals("application/json", StringComparison.OrdinalIgnoreCase)) { user = JObject.Parse(userInfoResponse); } else if (contentType.MediaType.Equals("application/jwt", StringComparison.OrdinalIgnoreCase)) { var userInfoEndpointJwt = new JwtSecurityToken(userInfoResponse); user = JObject.FromObject(userInfoEndpointJwt.Payload); } else { return(AuthenticateResult.Fail("Unknown response type: " + contentType.MediaType)); } var userInformationReceivedContext = await RunUserInformationReceivedEventAsync(ticket, message, user); AuthenticateResult result; if (userInformationReceivedContext.CheckEventResult(out result)) { return(result); } ticket = userInformationReceivedContext.Ticket; user = userInformationReceivedContext.User; Options.ProtocolValidator.ValidateUserInfoResponse(new OpenIdConnectProtocolValidationContext() { UserInfoEndpointResponse = userInfoResponse, ValidatedIdToken = jwt, }); var identity = (ClaimsIdentity)ticket.Principal.Identity; foreach (var claim in identity.Claims) { // If this claimType is mapped by the JwtSeurityTokenHandler, then this property will be set var shortClaimTypeName = claim.Properties.ContainsKey(JwtSecurityTokenHandler.ShortClaimTypeProperty) ? claim.Properties[JwtSecurityTokenHandler.ShortClaimTypeProperty] : string.Empty; // checking if claim in the identity (generated from id_token) has the same type as a claim retrieved from userinfo endpoint JToken value; var isClaimIncluded = user.TryGetValue(claim.Type, out value) || user.TryGetValue(shortClaimTypeName, out value); // if a same claim exists (matching both type and value) both in id_token identity and userinfo response, remove the json entry from the userinfo response if (isClaimIncluded && claim.Value.Equals(value.ToString(), StringComparison.Ordinal)) { if (!user.Remove(claim.Type)) { user.Remove(shortClaimTypeName); } } } // adding remaining unique claims from userinfo endpoint to the identity foreach (var pair in user) { JToken value; var claimValue = user.TryGetValue(pair.Key, out value) ? value.ToString() : null; identity.AddClaim(new Claim(pair.Key, claimValue, ClaimValueTypes.String, jwt.Issuer)); } return(AuthenticateResult.Success(ticket)); }