private async Task OnClientAuthenticated(OpenIdAuthenticatedContext context) { var userManager = context.HttpContext.RequestServices.GetService <SteamUsersController>(); var steamId = ulong.Parse(new Uri(context.Identifier).Segments.Last()); if (userManager != null && !await userManager.IsRegisteredAsync(steamId.ToString())) { await userManager.RegisterUserAsync(steamId.ToString()); } if (userManager != null && context.UserPayload != null) { await using var stream = new MemoryStream(); var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true }); context.UserPayload.RootElement.GetProperty("response").GetProperty("players").WriteTo(writer); await writer.FlushAsync(); var json = Encoding.UTF8.GetString(stream.ToArray()); var response = JsonConvert.DeserializeObject <SteamResponseModel>(json); foreach (var player in response.Players) { await userManager.UpdateUserAsync(player); } } context.Identity.AddClaim(new Claim("steamID", steamId.ToString())); var identity = new ClaimsPrincipal(context.Identity); context.HttpContext.User = identity; }
public static void RunClaimActions(this OpenIdAuthenticatedContext source, JObject model = null) { if (!ClaimMap.ContainsKey(source.Options)) { return; } if (model == null) { model = source.User; } foreach (var claim in ClaimMap[source.Options]) { var targetValue = model.SelectToken(claim.Value).ToString(); if (targetValue != null) { source.Identity.AddClaim(new Claim(claim.Type, targetValue, claim.ValueType, claim.Issuer)); } } }
protected override async Task <AuthenticationTicket> CreateTicketAsync( [NotNull] ClaimsIdentity identity, [NotNull] AuthenticationProperties properties, [NotNull] string identifier, [NotNull] IReadOnlyDictionary <string, string> attributes) { var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, properties, Scheme.Name); // Return the authentication ticket as-is if the user information endpoint has not been set. if (string.IsNullOrEmpty(Options.UserInformationEndpoint)) { Logger.LogInformation("The userinfo request was skipped because no userinfo endpoint was configured."); return(await RunAuthenticatedEventAsync()); } // Return the authentication ticket as-is if the application key has not been set. if (string.IsNullOrEmpty(Options.ApplicationKey)) { Logger.LogInformation("The userinfo request was skipped because no application key was configured."); return(await RunAuthenticatedEventAsync()); } // Note: prior to April 2018, the Steam identifier was prefixed with an HTTP base address. // Since then, the prefix is now an HTTPS address. The following logic supports both prefixes. if (identifier.StartsWith(SteamAuthenticationConstants.Namespaces.Identifier, StringComparison.Ordinal)) { identifier = identifier.Substring(SteamAuthenticationConstants.Namespaces.Identifier.Length); } else if (identifier.StartsWith(SteamAuthenticationConstants.Namespaces.LegacyIdentifier, StringComparison.Ordinal)) { identifier = identifier.Substring(SteamAuthenticationConstants.Namespaces.LegacyIdentifier.Length); } // Prevent the sign-in operation from completing if the claimed identifier is malformed. else { Logger.LogWarning("The userinfo request was skipped because an invalid identifier was received: {Identifier}.", identifier); throw new InvalidOperationException($"The OpenID claimed identifier '{identifier}' is not valid."); } var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary <string, string> { [SteamAuthenticationConstants.Parameters.Key] = Options.ApplicationKey, [SteamAuthenticationConstants.Parameters.SteamId] = identifier }); var request = new HttpRequestMessage(HttpMethod.Get, address); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(OpenIdAuthenticationConstants.Media.Json)); // Return the authentication ticket as-is if the userinfo request failed. var response = await Options.Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted); if (!response.IsSuccessStatusCode) { Logger.LogWarning("The userinfo request failed because an invalid response was received: the identity provider " + "returned returned a {Status} response with the following payload: {Headers} {Body}.", /* Status: */ response.StatusCode, /* Headers: */ response.Headers.ToString(), /* Body: */ await response.Content.ReadAsStringAsync()); throw new HttpRequestException("An error occurred while retrieving the user profile from Steam."); } using var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); // Try to extract the profile name of the authenticated user. var profile = payload.RootElement .GetProperty(SteamAuthenticationConstants.Parameters.Response) .GetProperty(SteamAuthenticationConstants.Parameters.Players) .EnumerateArray() .FirstOrDefault(); if (profile.ValueKind == JsonValueKind.Object && profile.TryGetProperty(SteamAuthenticationConstants.Parameters.Name, out var name)) { identity.AddClaim(new Claim(ClaimTypes.Name, name.GetString(), ClaimValueTypes.String, Options.ClaimsIssuer)); } return(await RunAuthenticatedEventAsync(payload)); async Task <AuthenticationTicket> RunAuthenticatedEventAsync(JsonDocument user = null) { var context = new OpenIdAuthenticatedContext(Context, Scheme, Options, ticket) { UserPayload = user }; if (user != null) { #pragma warning disable CS0618 context.User = JObject.Parse(user.RootElement.ToString()); #pragma warning restore CS0618 } // Copy the attributes to the context object. foreach (var attribute in attributes) { context.Attributes.Add(attribute); } await Events.Authenticated(context); // Note: return the authentication ticket associated // with the notification to allow replacing the ticket. return(context.Ticket); } }
protected override async Task <AuthenticationTicket> CreateTicketAsync( [NotNull] ClaimsIdentity identity, [NotNull] AuthenticationProperties properties, [NotNull] string identifier, [NotNull] IReadOnlyDictionary <string, string> attributes) { var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, properties, Scheme.Name); // Return the authentication ticket as-is if the // user information endpoint has not been set. if (string.IsNullOrEmpty(Options.UserInformationEndpoint)) { Logger.LogInformation("The userinfo request was skipped because no userinfo endpoint was configured."); return(ticket); } // Return the authentication ticket as-is // if the application key has not been set. if (string.IsNullOrEmpty(Options.ApplicationKey)) { Logger.LogInformation("The userinfo request was skipped because no application key was configured."); return(ticket); } // Note: prior to April 2018, the Steam identifier was prefixed with an HTTP base address. // Since then, the prefix is now an HTTPS address. The following logic supports both prefixes. if (identifier.StartsWith(SteamAuthenticationConstants.Namespaces.Identifier, StringComparison.Ordinal)) { identifier = identifier.Substring(SteamAuthenticationConstants.Namespaces.Identifier.Length); } else if (identifier.StartsWith(SteamAuthenticationConstants.Namespaces.LegacyIdentifier, StringComparison.Ordinal)) { identifier = identifier.Substring(SteamAuthenticationConstants.Namespaces.LegacyIdentifier.Length); } // Return the authentication ticket as-is if the claimed identifier is malformed. else { Logger.LogWarning("The userinfo request was skipped because an invalid identifier was received: {Identifier}.", identifier); return(ticket); } var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary <string, string> { [SteamAuthenticationConstants.Parameters.Key] = Options.ApplicationKey, [SteamAuthenticationConstants.Parameters.SteamId] = identifier }); var request = new HttpRequestMessage(HttpMethod.Get, address); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(OpenIdAuthenticationConstants.Media.Json)); // Return the authentication ticket as-is if the userinfo request failed. var response = await Options.HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted); if (!response.IsSuccessStatusCode) { Logger.LogWarning("The userinfo request failed because an invalid response was received: the identity provider " + "returned returned a {Status} response with the following payload: {Headers} {Body}.", /* Status: */ response.StatusCode, /* Headers: */ response.Headers.ToString(), /* Body: */ await response.Content.ReadAsStringAsync()); return(ticket); } var payload = JObject.Parse(await response.Content.ReadAsStringAsync()); // Try to extract the profile name of the authenticated user. var profile = payload.Value <JObject>(SteamAuthenticationConstants.Parameters.Response) ?.Value <JArray>(SteamAuthenticationConstants.Parameters.Players) ?[0]?.Value <string>(SteamAuthenticationConstants.Parameters.Name); if (!string.IsNullOrEmpty(profile)) { identity.AddClaim(new Claim(ClaimTypes.Name, profile, ClaimValueTypes.String, Options.ClaimsIssuer)); } var context = new OpenIdAuthenticatedContext(Context, Scheme, Options, ticket) { User = payload }; // Copy the attributes to the context object. foreach (var attribute in attributes) { context.Attributes.Add(attribute); } await Events.Authenticated(context); // Note: return the authentication ticket associated // with the notification to allow replacing the ticket. return(context.Ticket); }
/// <summary> /// Defines a notification invoked when the user is authenticated by the identity provider. /// </summary> /// <param name="context">The context of the event carries information in and results out.</param> /// <returns>Task to enable asynchronous execution</returns> public virtual Task Authenticated(OpenIdAuthenticatedContext context) => OnAuthenticated(context);