public AuthorizationModule() { Get["/connect/authorize", runAsync : true] = async(parameters, cancellationToken) => { this.CreateNewCsrfToken(); this.RequiresMSOwinAuthentication(); // Note: when a fatal error occurs during the request processing, an OpenID Connect response // is prematurely forged and added to the ASP.NET context by OpenIdConnectServerHandler. // You can safely remove this part and let ASOS automatically handle the unrecoverable errors // by switching ApplicationCanDisplayErrors to false in Startup.cs. var response = OwinContext.GetOpenIdConnectResponse(); if (response != null) { return(View["Error.cshtml", response]); } // Extract the authorization request from the OWIN environment. var request = OwinContext.GetOpenIdConnectRequest(); if (request == null) { return(View["Error.cshtml", new OpenIdConnectMessage { Error = "invalid_request", ErrorDescription = "An internal error has occurred" }]); } // Note: ASOS automatically ensures that an application corresponds to the client_id specified // in the authorization request by calling IOpenIdConnectServerProvider.ValidateAuthorizationRequest. // In theory, this null check shouldn't be needed, but a race condition could occur if you // manually removed the application details from the database after the initial check made by ASOS. var application = await GetApplicationAsync(request.ClientId, cancellationToken); if (application == null) { return(View["Error.cshtml", new OpenIdConnectMessage { Error = "invalid_client", ErrorDescription = "Details concerning the calling client application cannot be found in the database" }]); } // Note: in a real world application, you'd probably // prefer creating a specific view model. return(View["Authorize.cshtml", new { Application = application, Request = request }]); }; Post["/connect/authorize/accept", runAsync : true] = async(parameters, cancellationToken) => { this.RequiresMSOwinAuthentication(); this.ValidateCsrfToken(); var response = OwinContext.GetOpenIdConnectResponse(); if (response != null) { return(View["Error.cshtml", response]); } var request = OwinContext.GetOpenIdConnectRequest(); if (request == null) { return(View["Error.cshtml", new OpenIdConnectMessage { Error = "invalid_request", ErrorDescription = "An internal error has occurred" }]); } // Create a new ClaimsIdentity containing the claims that // will be used to create an id_token, a token or a code. var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationType); foreach (var claim in OwinContext.Authentication.User.Claims) { // Allow ClaimTypes.Name to be added in the id_token. // ClaimTypes.NameIdentifier is automatically added, even if its // destination is not defined or doesn't include "id_token". // The other claims won't be visible for the client application. if (claim.Type == ClaimTypes.Name) { claim.SetDestinations(OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); } identity.AddClaim(claim); } var application = await GetApplicationAsync(request.ClientId, CancellationToken.None); if (application == null) { return(View["Error.cshtml", new OpenIdConnectMessage { Error = "invalid_client", ErrorDescription = "Details concerning the calling client application cannot be found in the database" }]); } // Create a new ClaimsIdentity containing the claims associated with the application. // Note: setting identity.Actor is not mandatory but can be useful to access // the whole delegation chain from the resource server (see ResourceModule.cs). identity.Actor = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationType); identity.Actor.AddClaim(ClaimTypes.NameIdentifier, application.ApplicationID); identity.Actor.AddClaim(ClaimTypes.Name, application.DisplayName, OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); // Create a new authentication ticket holding the user identity. var ticket = new AuthenticationTicket(identity, new AuthenticationProperties()); // Set the list of scopes granted to the client application. // Note: this sample always grants the "openid", "email" and "profile" scopes // when they are requested by the client application: a real world application // would probably display a form allowing to select the scopes to grant. ticket.SetScopes(new[] { /* openid: */ OpenIdConnectConstants.Scopes.OpenId, /* email: */ OpenIdConnectConstants.Scopes.Email, /* profile: */ OpenIdConnectConstants.Scopes.Profile, /* offline_access: */ OpenIdConnectConstants.Scopes.OfflineAccess }.Intersect(request.GetScopes())); // Set the resources servers the access token should be issued for. ticket.SetResources("resource_server"); // This call will ask ASOS to serialize the specified identity to build appropriate tokens. // Note: you should always make sure the identities you return contain ClaimTypes.NameIdentifier claim. // In this sample, the identity always contains the name identifier returned by the external provider. OwinContext.Authentication.SignIn(ticket.Properties, ticket.Identity); return(HttpStatusCode.OK); }; Post["/connect/authorize/deny"] = parameters => { this.RequiresMSOwinAuthentication(); this.ValidateCsrfToken(); var response = OwinContext.GetOpenIdConnectResponse(); if (response != null) { return(View["Error.cshtml", response]); } // Extract the authorization request from the cache, the query string or the request form. var request = OwinContext.GetOpenIdConnectRequest(); if (request == null) { return(View["Error.cshtml", new OpenIdConnectMessage { Error = "invalid_request", ErrorDescription = "An internal error has occurred" }]); } // Notify ASOS that the authorization grant has been denied by the resource owner. // Note: OpenIdConnectServerHandler will automatically take care of redirecting // the user agent to the client application using the appropriate response_mode. OwinContext.Authentication.Forbid(OpenIdConnectServerDefaults.AuthenticationType); return(HttpStatusCode.Forbidden); }; Get["/connect/logout", runAsync : true] = async(parameters, cancellationToken) => { var response = OwinContext.GetOpenIdConnectResponse(); if (response != null) { return(View["Error.cshtml", response]); } // When invoked, the logout endpoint might receive an unauthenticated request if the server cookie has expired. // When the client application sends an id_token_hint parameter, the corresponding identity can be retrieved // using AuthenticateAsync or using User when the authorization server is declared as AuthenticationMode.Active. var identity = await OwinContext.Authentication.AuthenticateAsync(OpenIdConnectServerDefaults.AuthenticationType); // Extract the logout request from the OWIN environment. var request = OwinContext.GetOpenIdConnectRequest(); if (request == null) { return(View["Error.cshtml", new OpenIdConnectMessage { Error = "invalid_request", ErrorDescription = "An internal error has occurred" }]); } return(View["Logout.cshtml", Tuple.Create(request, identity)]); }; Post["/connect/logout"] = parameters => { this.ValidateCsrfToken(); var response = OwinContext.GetOpenIdConnectResponse(); if (response != null) { return(View["Error.cshtml", response]); } // Ask the cookies middleware to delete the local cookie created // when the user agent is redirected from the external identity provider // after a successful authentication flow (e.g Google or Facebook) and // redirect the user agent to the post_logout_redirect_uri specified by the client application. OwinContext.Authentication.SignOut("ServerCookie", OpenIdConnectServerDefaults.AuthenticationType); return(HttpStatusCode.OK); }; }
public async Task <IActionResult> Exchange(OpenIdConnectRequest request) { if (request.IsPasswordGrantType()) { var credentials = await _unitOfWork.Accounts .Include("User.Roles.Role.Permissions.Permission") .FirstOrDefaultAsync(c => c.Username == request.Username); if (credentials == null) { return(Forbid(OpenIdConnectServerDefaults.AuthenticationScheme)); } if (!BCrypt.Net.BCrypt.Verify(request.Password, credentials.Password)) { return(Forbid(OpenIdConnectServerDefaults.AuthenticationScheme)); } // Create a new ClaimsIdentity holding the user identity. var identity = new ClaimsIdentity( OpenIdConnectServerDefaults.AuthenticationScheme, OpenIdConnectConstants.Claims.Name, OpenIdConnectConstants.Claims.Role ); // Add a "sub" claim containing the user identifier, and attach // the "access_token" destination to allow OpenIddict to store it // in the access token, so it can be retrieved from your controllers. identity.AddClaim(OpenIdConnectConstants.Claims.Username, credentials.Username, OpenIdConnectConstants.Destinations.IdentityToken, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim("id", credentials.User.Id.ToString(), OpenIdConnectConstants.Destinations.IdentityToken, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim(OpenIdConnectConstants.Claims.Subject, credentials.User.Id.ToString(), OpenIdConnectConstants.Destinations.IdentityToken); identity.AddClaim(OpenIdConnectConstants.Claims.Name, credentials.User.Name, OpenIdConnectConstants.Destinations.IdentityToken); identity.AddClaim(OpenIdConnectConstants.Claims.FamilyName, credentials.User.LastName, OpenIdConnectConstants.Destinations.IdentityToken); identity.AddClaim(OpenIdConnectConstants.Claims.GivenName, credentials.User.FirstName, OpenIdConnectConstants.Destinations.IdentityToken); // ... add other claims, if necessary. var principal = new ClaimsPrincipal(identity); // Claims will not be associated with specific destinations by default, so we must indicate whether they should // be included or not in access and identity tokens. var authProperties = new AuthenticationProperties { AllowRefresh = true }; // Create a new authentication ticket for the user's principal var ticket = new AuthenticationTicket( principal, authProperties, OpenIdConnectServerDefaults.AuthenticationScheme); var roles = credentials.User.Roles.Select(r => r.Role); var permissions = roles.SelectMany(p => p.Permissions, (role, permission) => permission.Permission.Name).ToList(); // common scopes permissions.AddRange(new[] { OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.Email, OpenIdConnectConstants.Scopes.Profile, OpenIdConnectConstants.Scopes.OfflineAccess, OpenIddictConstants.Scopes.Roles }); // Include resources and scopes, as appropriate var scope = permissions.Intersect(request.GetScopes()); // Set resource servers ticket.SetResources("onlineshop"); ticket.SetScopes(scope); // Sign in the user return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme)); } // TODO add refresh token grant type else { return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidRequest, ErrorDescription = "The specified grant type is not supported." })); } }
public async Task <IActionResult> Accept(CancellationToken cancellationToken) { var response = HttpContext.GetOpenIdConnectResponse(); if (response != null) { return(View("Error", response)); } var request = HttpContext.GetOpenIdConnectRequest(); if (request == null) { return(View("Error", new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.ServerError, ErrorDescription = "An internal error has occurred" })); } // Create a new ClaimsIdentity containing the claims that // will be used to create an id_token, a token or a code. var identity = new ClaimsIdentity( OpenIdConnectServerDefaults.AuthenticationScheme, OpenIdConnectConstants.Claims.Name, OpenIdConnectConstants.Claims.Role); // Note: the "sub" claim is mandatory and an exception is thrown if this claim is missing. identity.AddClaim( new Claim(OpenIdConnectConstants.Claims.Subject, User.FindFirst(ClaimTypes.NameIdentifier).Value) .SetDestinations(OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken)); identity.AddClaim( new Claim(OpenIdConnectConstants.Claims.Name, User.FindFirst(ClaimTypes.Name).Value) .SetDestinations(OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken)); var application = await GetApplicationAsync(request.ClientId, cancellationToken); if (application == null) { return(View("Error", new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidClient, ErrorDescription = "Details concerning the calling client application cannot be found in the database" })); } // Create a new authentication ticket holding the user identity. var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); // Set the list of scopes granted to the client application. // Note: this sample always grants the "openid", "email" and "profile" scopes // when they are requested by the client application: a real world application // would probably display a form allowing to select the scopes to grant. ticket.SetScopes(new[] { /* openid: */ OpenIdConnectConstants.Scopes.OpenId, /* email: */ OpenIdConnectConstants.Scopes.Email, /* profile: */ OpenIdConnectConstants.Scopes.Profile, /* offline_access: */ OpenIdConnectConstants.Scopes.OfflineAccess }.Intersect(request.GetScopes())); // Set the resources servers the access token should be issued for. ticket.SetResources("resource_server"); // Returning a SignInResult will ask ASOS to serialize the specified identity to build appropriate tokens. return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme)); }
// [ValidateAntiForgeryToken] public async Task <IActionResult> Accept(CancellationToken cancellationToken) { var response = HttpContext.GetOpenIdConnectResponse(); if (response != null) { return(View("Error", response)); } var request = HttpContext.GetOpenIdConnectRequest(); if (request == null) { return(View("Error", new OpenIdConnectMessage { Error = OpenIdConnectConstants.Errors.ServerError, ErrorDescription = "An internal error has occurred" })); } // Remove the authorization request from the user session. if (!string.IsNullOrEmpty(request.GetRequestId())) { HttpContext.Session.Remove("authorization-request:" + request.GetRequestId()); } var scopes = request.GetScopes().ToList(); var claims = HttpContext.User.Claims; var identity = _userManager.CreateIdentity(scopes, claims); var application = await _applicationRepository.GetByIdAsync(request.ClientId); if (application == null) { return(View("Error", new OpenIdConnectMessage { Error = OpenIdConnectConstants.Errors.InvalidClient, ErrorDescription = "Details concerning the calling client application cannot be found in the database" })); } await _authorizationActionHandler.AddTrustedApplication(_userManager.GetCurrentUserId(), application.ApplicationId); identity.Actor = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme); identity.Actor.AddClaim(ClaimTypes.NameIdentifier, application.ApplicationId); identity.Actor.AddClaim(ClaimTypes.Name, application.DisplayName, OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); // Create a new authentication ticket holding the user identity. var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); // Set the list of scopes granted to the client application. // Note: this sample always grants the "openid", "email" and "profile" scopes // when they are requested by the client application: a real world application // would probably display a form allowing to select the scopes to grant. ticket.SetScopes(new[] { OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.Email, OpenIdConnectConstants.Scopes.Profile, OpenIdConnectConstants.Scopes.OfflineAccess }.Intersect(request.GetScopes())); // Set the resources servers the access token should be issued for. ticket.SetResources("resource_server"); return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme)); }
private async Task <AuthenticationTicket> DeserializeAccessTokenAsync(string token, OpenIdConnectRequest request) { var notification = new DeserializeAccessTokenContext(Context, Options, request, token) { DataFormat = Options.AccessTokenFormat, SecurityTokenHandler = Options.AccessTokenHandler }; // Note: ValidateAudience and ValidateLifetime are always set to false: // if necessary, the audience and the expiration can be validated // in InvokeIntrospectionEndpointAsync or InvokeTokenEndpointAsync. notification.TokenValidationParameters = new TokenValidationParameters { IssuerSigningKeys = Options.SigningCredentials.Select(credentials => credentials.SigningKey), ValidIssuer = Context.GetIssuer(Options), ValidateAudience = false, ValidateLifetime = false }; await Options.Provider.DeserializeAccessToken(notification); if (notification.HandledResponse || notification.Ticket != null) { notification.Ticket.SetUsage(OpenIdConnectConstants.Usages.AccessToken); return(notification.Ticket); } else if (notification.Skipped) { return(null); } var handler = notification.SecurityTokenHandler as ISecurityTokenValidator; if (handler == null) { return(notification.DataFormat?.Unprotect(token)); } SecurityToken securityToken; ClaimsPrincipal principal; try { if (!handler.CanReadToken(token)) { Options.Logger.LogDebug("The access token handler refused to read the token: {Token}", token); return(null); } principal = handler.ValidateToken(token, notification.TokenValidationParameters, out securityToken); } catch (Exception exception) { Options.Logger.LogDebug("An exception occured when deserializing an access token: {Message}", exception.Message); return(null); } // Parameters stored in AuthenticationProperties are lost // when the identity token is serialized using a security token handler. // To mitigate that, they are inferred from the claims or the security token. var properties = new AuthenticationProperties { ExpiresUtc = securityToken.ValidTo, IssuedUtc = securityToken.ValidFrom }; var ticket = new AuthenticationTicket((ClaimsIdentity)principal.Identity, properties); var audiences = principal.FindAll(OpenIdConnectConstants.Claims.Audience); if (audiences.Any()) { ticket.SetAudiences(audiences.Select(claim => claim.Value)); } var presenters = principal.FindAll(OpenIdConnectConstants.Claims.AuthorizedParty); if (presenters.Any()) { ticket.SetPresenters(presenters.Select(claim => claim.Value)); } var scopes = principal.FindAll(OpenIdConnectConstants.Claims.Scope); if (scopes.Any()) { ticket.SetScopes(scopes.Select(claim => claim.Value)); } var identifier = principal.FindFirst(OpenIdConnectConstants.Claims.JwtId); if (identifier != null) { ticket.SetTicketId(identifier.Value); } var usage = principal.FindFirst(OpenIdConnectConstants.Claims.Usage); if (usage != null) { ticket.SetUsage(usage.Value); } var confidentiality = principal.FindFirst(OpenIdConnectConstants.Claims.ConfidentialityLevel); if (confidentiality != null) { ticket.SetProperty(OpenIdConnectConstants.Properties.ConfidentialityLevel, confidentiality.Value); } // Ensure the received ticket is an access token. if (!ticket.IsAccessToken()) { Options.Logger.LogDebug("The received token was not an access token: {Token}.", token); return(null); } return(ticket); }
public override async Task HandleTokenRequest(HandleTokenRequestContext context) { var isValid = false; if (context.Request.IsPasswordGrantType()) { //Caso o usuário informe usuário e senha na requisição do token, você deve validar se é válido isValid = context.Request.Username == "teste" && context.Request.Password == "teste"; } else if (context.Request.IsRefreshTokenGrantType()) { //Caso seja um refresh_token, você deve verificar se o usuário continua tendo acesso //aos recursos e definir como válido ou não, note que não temos mais senha aqui //mas o token garante quem é o sujeito var login = context.Ticket.Principal.GetClaim(ClaimTypes.NameIdentifier); isValid = login == "teste"; } if (!isValid) { //Aqui é a hora que define a requisição como inválida context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "Usuário/senha inválidos." ); return; } var identity = new ClaimsIdentity(context.Options.AuthenticationScheme); //Aqui a gente cria os dados que queremos colocar no token //Como são dados de identificação não sensíveis, posso colocar no: //IdentityToken: Pode ser decriptado nos clients, serve para identificar em recursos externos //AccessToken: Token criptografado, que apenas o servidor que gerou (ou que possui a chave) possam decriptar as informações identity.AddClaim(ClaimTypes.Email, "*****@*****.**", Destinations.AccessToken, Destinations.IdentityToken); identity.AddClaim(ClaimTypes.GivenName, "Nome", Destinations.AccessToken, Destinations.IdentityToken); //Aqui são dados mais sensíveis, posso travar para enviar apenas no AccessToken identity.AddClaim(ClaimTypes.NameIdentifier, "teste", Destinations.AccessToken); identity.AddClaim(MyClaims.Perfil, MyPolicies.Vendedor, Destinations.AccessToken); //Coloca os dados no token var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), context.Options.AuthenticationScheme ); //Define os escopos do token, esta informação pode ser recebida no request e revalidada para enviar apenas o que o client pediu //Caso não vá precisar autenticar em outros serviços (99% das vezes) você pode suprimir o OpenId //Caso não queira permitir o refresh da autorização sem senha, pode suprimir o OfflineAccess ticket.SetScopes( Scopes.OpenId, Scopes.OfflineAccess ); //Você também pode informar os recursos a que este usuário tem acesso, isto será enviado no Identity Token, para o client travar um menu por ex.... //ticket.SetResources("ApiCadastro, ApiCliente, ApiVenda, ..."); context.Validate(ticket); }
public async override Task GrantResourceOwnerCredentials( GrantResourceOwnerCredentialsContext context) { _authService = (IAuthService)context.HttpContext.RequestServices.GetService(typeof(IAuthService)); Client client = _authService.FindClient(context.ClientId); string allowedOrigin = string.Empty; allowedOrigin = client.AllowedOrigin == null ? "*" : client.AllowedOrigin; //comentado pois está dando conflito com cors adicionado anteriormente //context.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin }); var user = await _authService.GetUsuarioEmail(context.UserName); var valid = await _authService.CheckPasswordAsync(user, context.Password); if (valid) { int casaId = await _authService.GetCasaSelecionada(user); //verifica se usuario esta bloqueado para aquela casa if (_authService.AcessoUsuarioBloqueado(user.Id, casaId)) { //tenta obter acesso em outra casa int novaCasaSelec = _authService.TentaSelecOutraCasa(user.Id, casaId); if (novaCasaSelec == 0) { context.Reject("O seu acesso foi bloqueado"); return; } casaId = novaCasaSelec; } var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme); foreach (var claim in _authService.GetClaims(user, casaId)) { identity.AddClaim(claim.Type, claim.Value, "access_token", "id_token"); } identity.AddClaim("casa", casaId.ToString(), "access_token", "id_token"); identity.AddClaim(ClaimTypes.NameIdentifier, user.Id, "access_token", "id_token"); identity.AddClaim(ClaimTypes.Name, user.UserName, "access_token", "id_token"); var principal = new ClaimsPrincipal(identity); var props = new AuthenticationProperties(new Dictionary <string, string> { { "client_id", (context.ClientId == null) ? string.Empty : context.ClientId }, { "userName", context.UserName } }); var ticket = new AuthenticationTicket(principal, props, OpenIdConnectServerDefaults.AuthenticationScheme); List <string> scopes = new List <string>(); if (context.Request.HasScope("offline_access")) { scopes.Add("offline_access"); } ticket.SetScopes(scopes); context.Validate(ticket); } }
public override async Task GrantResourceOwnerCredentials([NotNull] GrantResourceOwnerCredentialsContext context) { var services = context.HttpContext.RequestServices.GetRequiredService <OpenIddictServices <TUser, TApplication> >(); var user = await services.Users.FindByNameAsync(context.UserName); if (user == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "Invalid credentials."); return; } // Ensure the user is allowed to sign in. if (!await services.SignIn.CanSignInAsync(user)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "The user is not allowed to sign in."); return; } // Ensure the user is not already locked out. if (services.Users.SupportsUserLockout && await services.Users.IsLockedOutAsync(user)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "Account locked out."); return; } // Ensure the password is valid. if (!await services.Users.CheckPasswordAsync(user, context.Password)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "Invalid credentials."); if (services.Users.SupportsUserLockout) { await services.Users.AccessFailedAsync(user); // Ensure the user is not locked out. if (await services.Users.IsLockedOutAsync(user)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "Account locked out."); } } return; } if (services.Users.SupportsUserLockout) { await services.Users.ResetAccessFailedCountAsync(user); } // Reject the token request if two-factor authentication has been enabled by the user. if (services.Users.SupportsUserTwoFactor && await services.Users.GetTwoFactorEnabledAsync(user)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "Two-factor authentication is required for this account."); return; } // Return an error if the username corresponds to the registered // email address and if the "email" scope has not been requested. if (context.Request.HasScope(OpenIdConnectConstants.Scopes.Profile) && !context.Request.HasScope(OpenIdConnectConstants.Scopes.Email) && string.Equals(await services.Users.GetUserNameAsync(user), await services.Users.GetEmailAsync(user), StringComparison.OrdinalIgnoreCase)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The 'email' scope is required."); return; } var identity = await services.Applications.CreateIdentityAsync(user, context.Request.GetScopes()); Debug.Assert(identity != null); // Create a new authentication ticket holding the user identity. var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), context.Options.AuthenticationScheme); ticket.SetResources(context.Request.GetResources()); ticket.SetScopes(context.Request.GetScopes()); context.Validate(ticket); }
private static TestServer CreateAuthorizationServer(Action <OpenIddictBuilder> configuration = null) { var builder = new WebHostBuilder(); builder.UseEnvironment("Testing"); builder.ConfigureLogging(options => options.AddDebug()); builder.ConfigureServices(services => { services.AddOptions(); services.AddDistributedMemoryCache(); // Note: the following client_id/client_secret are fake and are only // used to test the metadata returned by the discovery endpoint. services.AddAuthentication() .AddFacebook(options => { options.ClientId = "16018790-E88E-4553-8036-BB342579FF19"; options.ClientSecret = "3D6499AF-5607-489B-815A-F3ACF1617296"; options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) .AddGoogle(options => { options.ClientId = "BAF437A5-87FA-4D06-8EFD-F9BA96CCEDC4"; options.ClientSecret = "27DF07D3-6B03-4EE0-95CD-3AC16782216B"; options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; }); // Replace the default OpenIddict managers. services.AddSingleton(CreateApplicationManager()); services.AddSingleton(CreateAuthorizationManager()); services.AddSingleton(CreateScopeManager()); services.AddSingleton(CreateTokenManager()); services.AddOpenIddict(options => { // Disable the transport security requirement during testing. options.DisableHttpsRequirement(); // Enable the tested endpoints. options.EnableAuthorizationEndpoint(AuthorizationEndpoint) .EnableIntrospectionEndpoint(IntrospectionEndpoint) .EnableLogoutEndpoint(LogoutEndpoint) .EnableRevocationEndpoint(RevocationEndpoint) .EnableTokenEndpoint(TokenEndpoint) .EnableUserinfoEndpoint(UserinfoEndpoint); // Enable the tested flows. options.AllowAuthorizationCodeFlow() .AllowClientCredentialsFlow() .AllowImplicitFlow() .AllowPasswordFlow() .AllowRefreshTokenFlow(); // Register the X.509 certificate used to sign the identity tokens. options.AddSigningCertificate( assembly: typeof(OpenIddictProviderTests).GetTypeInfo().Assembly, resource: "OpenIddict.Tests.Certificate.pfx", password: "******"); // Note: overriding the default data protection provider is not necessary for the tests to pass, // but is useful to ensure unnecessary keys are not persisted in testing environments, which also // helps make the unit tests run faster, as no registry or disk access is required in this case. options.UseDataProtectionProvider(new EphemeralDataProtectionProvider(new LoggerFactory())); // Run the configuration delegate // registered by the unit tests. configuration?.Invoke(options); }); }); builder.Configure(app => { app.UseStatusCodePages(context => { context.HttpContext.Response.Headers[HeaderNames.ContentType] = "application/json"; return(context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(new { error_custom = OpenIdConnectConstants.Errors.InvalidRequest }))); }); app.Use(next => context => { if (context.Request.Path != "/authorize-status-code-middleware" && context.Request.Path != "/logout-status-code-middleware") { var feature = context.Features.Get <IStatusCodePagesFeature>(); feature.Enabled = false; } return(next(context)); }); app.UseAuthentication(); app.Run(context => { var request = context.GetOpenIdConnectRequest(); if (request.IsAuthorizationRequest() || request.IsTokenRequest()) { var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme); identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "Bob le Magnifique"); var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); ticket.SetScopes(request.GetScopes()); if (request.HasParameter("attach-authorization")) { ticket.SetProperty(OpenIddictConstants.Properties.AuthorizationId, "1AF06AB2-A0FC-4E3D-86AF-E04DA8C7BE70"); } if (request.HasParameter("do-not-flow-original-properties")) { var properties = new AuthenticationProperties(); properties.SetProperty("custom_property_in_new_ticket", "new_value"); return(context.SignInAsync(ticket.AuthenticationScheme, ticket.Principal, properties)); } return(context.SignInAsync(ticket.AuthenticationScheme, ticket.Principal, ticket.Properties)); } else if (request.IsLogoutRequest()) { return(context.SignOutAsync(OpenIdConnectServerDefaults.AuthenticationScheme)); } else if (request.IsUserinfoRequest()) { context.Response.Headers[HeaderNames.ContentType] = "application/json"; return(context.Response.WriteAsync(JsonConvert.SerializeObject(new { access_token = request.AccessToken, sub = "Bob le Bricoleur" }))); } return(Task.FromResult(0)); }); }); return(new TestServer(builder)); }
// Implementing HandleTokenRequest to issue an authentication ticket containing the user claims public override async Task HandleTokenRequest(HandleTokenRequestContext context) { // Only handle grant_type=password requests and let ASOS // process grant_type=refresh_token requests automatically. if (context.Request.IsPasswordGrantType()) { // Get user login data. var loginDetails = await LoginProvider.GetEntity(context.Request.Username); if (loginDetails == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "Invalid credentials."); return; } if (loginDetails.UniqueId != context.Request.Username) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "Invalid credentials."); return; } // Get user data var user = await RavenDatabaseProvider.GetEntity <User>(loginDetails.UserId); if (user == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "Invalid username or password."); return; } // Ensure the user is allowed to sign in. if (await UserProvider.IsBannedAsync(user)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "The specified user is not allowed to sign in."); return; } // Ensure the user is not already locked out. if (LoginProvider.SupportsUserLockout && await LoginProvider.IsLockedOutAsync(loginDetails)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "Invalid credentials."); return; } // Ensure the password is valid. if (!LoginProvider.IsPasswordCorrect(loginDetails, context.Request.Password)) { if (LoginProvider.SupportsUserLockout) { // Increment lock out count await LoginProvider.AccessFailedAsync(loginDetails); } context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "Invalid credentials."); return; } if (LoginProvider.SupportsUserLockout) { // Reset lock out data await LoginProvider.ResetAccessFailedCountAsync(loginDetails); } var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme); // Note: the subject claim is always included in both identity and // access tokens, even if an explicit destination is not specified. identity.AddClaim(OpenIdConnectConstants.Claims.Subject, loginDetails.UserId); // Add user-id identity.AddClaim(ClaimTypes.Name, user.Id, OpenIdConnectConstants.Destinations.AccessToken); // Add user-role identity.AddClaim(ClaimTypes.Role, user.Type.ToString(), OpenIdConnectConstants.Destinations.AccessToken); // Create a new authentication ticket holding the user identity. var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); // Set the list of scopes granted to the client application. // (specify offline_access to issue a refresh token). ticket.SetScopes(OpenIdConnectConstants.Scopes.OfflineAccess); context.Validate(ticket); } return; }
private async Task <AuthenticationTicket> CreateTicketAsync(OpenIdConnectRequest request, ApplicationUser user) { // Create a new ClaimsPrincipal containing the claims that // will be used to create an id_token, a token or a code. var principal = await _signInManager.CreateUserPrincipalAsync(user); var identity = (ClaimsIdentity)principal.Identity; // !! ADDING FIELD: this will include FavColor in generated JWT access tokens & id tokens var favColorClaim = new Claim("favColor", user.FavColor?.ToString() ?? "", ClaimValueTypes.String); favColorClaim.SetDestinations(OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); identity.AddClaim(favColorClaim); // Create a new authentication ticket holding the user identity. var ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); // Set the list of scopes granted to the client application. ticket.SetScopes(new[] { OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.Email, OpenIdConnectConstants.Scopes.Profile, OpenIddictConstants.Scopes.Roles }.Intersect(request.GetScopes())); ticket.SetResources(_configuration["Cierge:Audience"]); // Note: by default, claims are NOT automatically included in the access and identity tokens. // To allow OpenIddict to serialize them, you must attach them a destination, that specifies // whether they should be included in access tokens, in identity tokens or in both. foreach (var claim in ticket.Principal.Claims) { // Never include the security stamp in the access and identity tokens, as it's a secret value. if (claim.Type == _identityOptions.Value.ClaimsIdentity.SecurityStampClaimType) { continue; } var destinations = new List <string> { OpenIdConnectConstants.Destinations.AccessToken }; // Only add the iterated claim to the id_token if the corresponding scope was granted to the client application. // The other claims will only be added to the access_token, which is encrypted when using the default format. if ((claim.Type == OpenIdConnectConstants.Claims.Name && ticket.HasScope(OpenIdConnectConstants.Scopes.Profile)) || (claim.Type == OpenIdConnectConstants.Claims.Email && ticket.HasScope(OpenIdConnectConstants.Scopes.Email)) || (claim.Type == OpenIdConnectConstants.Claims.Role && ticket.HasScope(OpenIddictConstants.Claims.Roles))) { destinations.Add(OpenIdConnectConstants.Destinations.IdentityToken); } claim.SetDestinations(destinations); } return(ticket); }
public virtual async Task <IActionResult> Accept() { // Note: when a fatal error occurs during the request processing, an OpenID Connect response // is prematurely forged and added to the ASP.NET context by OpenIdConnectServerHandler. // In this case, the OpenID Connect request is null and cannot be used. // When the user agent can be safely redirected to the client application, // OpenIdConnectServerHandler automatically handles the error and MVC is not invoked. // You can safely remove this part and let AspNet.Security.OpenIdConnect.Server automatically // handle the unrecoverable errors by switching ApplicationCanDisplayErrors to false. var response = HttpContext.GetOpenIdConnectResponse(); if (response != null) { return(View("Error", response)); } // Extract the authorization request from the cache, // the query string or the request form. var request = HttpContext.GetOpenIdConnectRequest(); if (request == null) { return(View("Error", new OpenIdConnectMessage { Error = OpenIdConnectConstants.Errors.ServerError, ErrorDescription = "An internal error has occurred" })); } // Retrieve the user data using the unique identifier. var user = await Manager.FindByIdAsync(User.GetUserId()); if (user == null) { return(View("Error", new OpenIdConnectMessage { Error = OpenIdConnectConstants.Errors.ServerError, ErrorDescription = "An internal error has occurred" })); } // Create a new ClaimsIdentity containing the claims that // will be used to create an id_token, a token or a code. var identity = await Manager.CreateIdentityAsync(user, request.GetScopes()); Debug.Assert(identity != null); // Note: AspNet.Security.OpenIdConnect.Server automatically ensures an application // corresponds to the client_id specified in the authorization request using // IOpenIdConnectServerProvider.ValidateClientRedirectUri (see OpenIddictProvider.cs). var application = await Manager.FindApplicationByIdAsync(request.ClientId); // In theory, this null check is thus not strictly necessary. That said, a race condition // and a null reference exception could appear here if you manually removed the application // details from the database after the initial check made by AspNet.Security.OpenIdConnect.Server. if (application == null) { return(View("Error", new OpenIdConnectMessage { Error = OpenIdConnectConstants.Errors.InvalidClient, ErrorDescription = "Details concerning the calling client application cannot be found in the database" })); } // Create a new ClaimsIdentity containing the claims associated with the application. // Note: setting identity.Actor is not mandatory but can be useful to access // the whole delegation chain from the resource server (see ResourceController.cs). identity.Actor = new ClaimsIdentity(Options.AuthenticationScheme); identity.Actor.AddClaim(ClaimTypes.NameIdentifier, request.ClientId); identity.Actor.AddClaim(ClaimTypes.Name, await Manager.GetDisplayNameAsync(application), OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); // Create a new authentication ticket holding the user identity. var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), null, Options.AuthenticationScheme); ticket.SetResources(request.GetResources()); ticket.SetScopes(request.GetScopes()); // This call will instruct AspNet.Security.OpenIdConnect.Server to serialize // the specified identity to build appropriate tokens (id_token and token). // Note: you should always make sure the identities you return contain either // a 'sub' or a 'ClaimTypes.NameIdentifier' claim. In this case, the returned // identities always contain the name identifier returned by the external provider. await HttpContext.Authentication.SignInAsync(ticket.AuthenticationScheme, ticket.Principal, ticket.Properties); return(new EmptyResult()); }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions { HotModuleReplacement = false // Aurelia Webpack Plugin HMR currently has issues. Leave this set to false. }); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseOpenIdConnectServer(options => { // Enable the token endpoint. options.TokenEndpointPath = "/api/token"; // Implement OnValidateTokenRequest to support flows using the token endpoint. options.Provider.OnValidateTokenRequest = context => { // Reject token requests that don't use grant_type=password or grant_type=refresh_token. if (!context.Request.IsPasswordGrantType() && !context.Request.IsRefreshTokenGrantType()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "Only grant_type=password and refresh_token " + "requests are accepted by this server."); return(Task.FromResult(0)); } // Note: you can skip the request validation when the client_id // parameter is missing to support unauthenticated token requests. // if (string.IsNullOrEmpty(context.ClientId)) // { // context.Skip(); // // return Task.FromResult(0); // } // Note: to mitigate brute force attacks, you SHOULD strongly consider applying // a key derivation function like PBKDF2 to slow down the secret validation process. // You SHOULD also consider using a time-constant comparer to prevent timing attacks. if (string.Equals(context.ClientId, "client_id", StringComparison.Ordinal) && string.Equals(context.ClientSecret, "client_secret", StringComparison.Ordinal)) { context.Validate(); } // Note: if Validate() is not explicitly called, // the request is automatically rejected. return(Task.FromResult(0)); }; // Implement OnHandleTokenRequest to support token requests. options.Provider.OnHandleTokenRequest = context => { // Only handle grant_type=password token requests and let the // OpenID Connect server middleware handle the other grant types. if (context.Request.IsPasswordGrantType()) { // Implement context.Request.Username/context.Request.Password validation here. // Note: you can call context Reject() to indicate that authentication failed. // Using password derivation and time-constant comparer is STRONGLY recommended. if (!string.Equals(context.Request.Username, "Bob", StringComparison.Ordinal) || !string.Equals(context.Request.Password, "P@ssw0rd", StringComparison.Ordinal)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "Invalid user credentials."); return(Task.FromResult(0)); } var identity = new ClaimsIdentity(context.Options.AuthenticationScheme, OpenIdConnectConstants.Claims.Name, OpenIdConnectConstants.Claims.Role); // Add the mandatory subject/user identifier claim. identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "[unique id]"); // By default, claims are not serialized in the access/identity tokens. // Use the overload taking a "destinations" parameter to make sure // your claims are correctly inserted in the appropriate tokens. identity.AddClaim("urn:customclaim", "value", OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), context.Options.AuthenticationScheme); // Call SetScopes with the list of scopes you want to grant // (specify offline_access to issue a refresh token). ticket.SetScopes( OpenIdConnectConstants.Scopes.Profile, OpenIdConnectConstants.Scopes.OfflineAccess); context.Validate(ticket); } return(Task.FromResult(0)); }; options.SigningCredentials.AddCertificate("D1229DEE962DD394BC3659DED38E4B56629EB943"); }); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); routes.MapSpaFallbackRoute( name: "spa-fallback", defaults: new { controller = "Home", action = "Index" }); }); }
private async Task <AuthenticationTicket> CreateTicketAsync(OpenIdConnectRequest request, Users _user) { // Create a new ClaimsPrincipal containing the claims that // will be used to create an id_token, a token or a code. // var principal = await _signInManager.CreateUserPrincipalAsync(user); var identity = new ClaimsIdentity( OpenIddictServerDefaults.AuthenticationScheme, OpenIdConnectConstants.Claims.Name, OpenIdConnectConstants.Claims.Role); // Add a "sub" claim containing the user identifier, and attach // the "access_token" destination to allow OpenIddict to store it // in the access token, so it can be retrieved from your controllers. //Users _user = PatrolUserManager.GetUserByUserName(user.UserName); identity.AddClaim(OpenIdConnectConstants.Claims.Subject, _user.Userid.ToString(), OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim(OpenIdConnectConstants.Claims.Name, _user.Username, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim("userName", _user.Username, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim("empDisplayName", _user.Name, OpenIdConnectConstants.Destinations.AccessToken); // identity.AddClaim("mNO", "", // OpenIdConnectConstants.Destinations.AccessToken); // identity.AddClaim("empDeptCode", "", //OpenIdConnectConstants.Destinations.AccessToken); // identity.AddClaim("empDeptName", "", //OpenIdConnectConstants.Destinations.AccessToken); var userRoles = PatrolUserManager.GetRolesByUserId(_user.Userid); foreach (var role in userRoles) { identity.AddClaim(ClaimTypes.Role, role, OpenIdConnectConstants.Destinations.AccessToken); } var userLeftNavigation = identity.AddClaim("userLeftNavigation", PatrolUserManager.FetchLeftNavigationByUserId(_user.Userid), OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim("configuration", PatrolUserManager.GetUserPreferenceByUserId(_user.Userid, userRoles), OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim("role", JsonConvert.SerializeObject(userRoles.ToArray()), OpenIdConnectConstants.Destinations.AccessToken); //identity.AddClaim(ClaimTypes.Role, "ViewPatrolCarsRole", // OpenIdConnectConstants.Destinations.AccessToken); //identity.AddClaim(ClaimTypes.Role, "ViewPatrolCarsRole", // OpenIdConnectConstants.Destinations.AccessToken); // ... add other claims, if necessary. var principal = new ClaimsPrincipal(identity); // Create a new authentication ticket holding the user identity. var ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), OpenIddictServerDefaults.AuthenticationScheme); //if (!request.IsRefreshTokenGrantType()) //{ // Set the list of scopes granted to the client application. // Note: the offline_access scope must be granted // to allow OpenIddict to return a refresh token. ticket.SetScopes(new[] { OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.Email, OpenIdConnectConstants.Scopes.OfflineAccess, OpenIddictConstants.Scopes.Roles }.Intersect(request.GetScopes())); // Note: by default, claims are NOT automatically included in the access and identity tokens. // To allow OpenIddict to serialize them, you must attach them a destination, that specifies // whether they should be included in access tokens, in identity tokens or in both. foreach (var claim in ticket.Principal.Claims) { //// Never include the security stamp in the access and identity tokens, as it's a secret value. //if (claim.Type == _identityOptions.Value.ClaimsIdentity.SecurityStampClaimType) // continue; var destinations = new List <string> { OpenIdConnectConstants.Destinations.AccessToken }; destinations.Add(OpenIdConnectConstants.Destinations.IdentityToken); claim.SetDestinations(destinations); } return(ticket); }
public async Task <IActionResult> Accept(CancellationToken cancellationToken) { ApplicationUser au = await _userManager.GetUserAsync(HttpContext.User); if (au == null) { return(View("Error", new AuthorizeErrorViewModel() { Error = "No such user", ErrorDescription = "Failed to find specified user" })); } OpenIdConnectRequest request = HttpContext.GetOpenIdConnectRequest(); ClaimsIdentity identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme, OpenIdConnectConstants.Claims.Name, OpenIdConnectConstants.Claims.Role); // We serialize the user_id so we can determine which user the caller of this token is string userid = _userManager.GetUserId(HttpContext.User); identity.AddClaim( new Claim(OpenIdConnectConstants.Claims.Subject, userid) .SetDestinations(OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken)); // We serialize the grant_type so we can user discriminate rate-limits. AuthorizationCode grants have the highest rate-limit allowance identity.AddClaim( new Claim("grant_type", OpenIdConnectConstants.GrantTypes.AuthorizationCode) .SetDestinations(OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken)); // We serialize the client_id so we can monitor for usage patterns of a given app, and also to allow for app-based token revokes. identity.AddClaim( new Claim("client_id", request.ClientId) .SetDestinations(OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken)); RegisteredApplication ra = await(from entity in _mockifyContext.Applications where entity.ClientId == request.ClientId select entity).SingleOrDefaultAsync(cancellationToken); if (ra == null) { return(View("Error", new AuthorizeErrorViewModel { Error = OpenIdConnectConstants.Errors.InvalidClient, ErrorDescription = "Details concerning the calling client " + "application cannot be found in the database" })); } AuthenticationTicket ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); List <string> scopesToAdd = new List <string>() { OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.OfflineAccess, SpotifyScope.Public.Name, }; if (!String.IsNullOrWhiteSpace(request.Scope)) { foreach (string scope in request.Scope.Split(',')) { if (SpotifyScope.IdMap.ContainsKey(scope) && !scopesToAdd.Contains(scope)) { scopesToAdd.Add(scope); } } } ticket.SetScopes(scopesToAdd); ticket.SetResources("resource_server"); // ?? what is this Microsoft.AspNetCore.Mvc.SignInResult sr = SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme); return(sr); }
public async Task <IActionResult> ExchangeAsync(OpenIdConnectRequest request) { // Reject the token request if client_id or client_secret is missing. /* if (string.IsNullOrEmpty(request.ClientId) || string.IsNullOrEmpty(request.ClientSecret)) * { * return BadRequest(new OpenIdConnectResponse * { * Error = OpenIdConnectConstants.Errors.InvalidRequest, * ErrorDescription = "Missing credentials: ensure that your credentials were correctly " + * "flowed in the request body or in the authorization header" * }); * } */ // Retrieve the application details from the database. /* var application = await _applicationManager.FindByClientIdAsync(request.ClientId, HttpContext.RequestAborted); * * if (application == null) * { * return BadRequest(new OpenIdConnectResponse * { * Error = OpenIdConnectConstants.Errors.InvalidClient, * ErrorDescription = "The credentials is invalid." * }); * } */ if (request.IsPasswordGrantType()) { /* if (!string.Equals(application.Type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.Ordinal)) * { * return BadRequest(new OpenIdConnectResponse * { * Error = OpenIdConnectConstants.Errors.InvalidClient, * ErrorDescription = "Only confidential clients are allowed to use password grant type." * }); * } */ var user = _ctx.Users .Where(x => x.Email.Equals(request.Username)) .Where(x => x.ProviderName.Equals("EMAIL")) .FirstOrDefault(); //var user = await _userManager.FindByEmailAsync(request.Username); if (user == null) { return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidGrant, ErrorDescription = "The username/password couple is invalid." })); } var canSignIn = await _signInManager.CanSignInAsync(user); // Ensure the user is allowed to sign in. if (!canSignIn) { return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidGrant, ErrorDescription = "The specified user is not allowed to sign in." })); } // Reject the token request if two-factor authentication has been enabled by the user. if (_userManager.SupportsUserTwoFactor && await _userManager.GetTwoFactorEnabledAsync(user)) { return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidGrant, ErrorDescription = "The specified user is not allowed to sign in." })); } // Ensure the user is not already locked out. if (_userManager.SupportsUserLockout && await _userManager.IsLockedOutAsync(user)) { return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidGrant, ErrorDescription = "The username/password couple is invalid." })); } // Ensure the password is valid. if (!await _userManager.CheckPasswordAsync(user, request.Password)) { if (_userManager.SupportsUserLockout) { await _userManager.AccessFailedAsync(user); } return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidGrant, ErrorDescription = "The username/password couple is invalid." })); } if (_userManager.SupportsUserLockout) { await _userManager.ResetAccessFailedCountAsync(user); } var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme); identity.AddClaim(OpenIdConnectConstants.Claims.Subject, user.Id, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim(OpenIdConnectConstants.Claims.Email, user.Email, OpenIdConnectConstants.Destinations.AccessToken); if (user.FirstName != null) { identity.AddClaim(OpenIdConnectConstants.Claims.GivenName, user.FirstName, OpenIdConnectConstants.Destinations.AccessToken); } if (user.LastName != null) { identity.AddClaim(OpenIdConnectConstants.Claims.FamilyName, user.LastName, OpenIdConnectConstants.Destinations.AccessToken); } var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); ticket.SetScopes( OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.OfflineAccess, OpenIdConnectConstants.Scopes.Profile, OpenIdConnectConstants.Scopes.Email); return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme)); } if (request.IsAuthorizationCodeGrantType()) { // Retrieve the claims principal stored in the authorization code. var info = await HttpContext.AuthenticateAsync( OpenIdConnectServerDefaults.AuthenticationScheme); // Retrieve the user profile corresponding to the authorization code. // Note: if you want to automatically invalidate the authorization code // when the user password/roles change, use the following line instead: //var user = await _signInManager.ValidateSecurityStampAsync(info.Principal); var user = await _userManager.GetUserAsync(info.Principal); if (user == null) { return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidGrant, ErrorDescription = "The authorization code is no longer valid." })); } // Ensure the user is still allowed to sign in. if (!await _signInManager.CanSignInAsync(user)) { return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidGrant, ErrorDescription = "The user is no longer allowed to sign in." })); } // Create a new authentication ticket, but reuse the properties stored // in the authorization code, including the scopes originally granted. var ticket = await CreateTicketAsync(request, user, info.Properties); return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme)); } if (request.IsRefreshTokenGrantType()) { // Retrieve the claims principal stored in the refresh token. var info = await HttpContext.AuthenticateAsync( OpenIdConnectServerDefaults.AuthenticationScheme); // Retrieve the user profile corresponding to the refresh token. // Note: if you want to automatically invalidate the refresh token // when the user password/roles change, use the following line instead: var user = await _signInManager.ValidateSecurityStampAsync(info.Principal); //var user = await _userManager.GetUserAsync(info.Principal); if (user == null) { return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidGrant, ErrorDescription = "The refresh token is no longer valid." })); } // Ensure the user is still allowed to sign in. if (!await _signInManager.CanSignInAsync(user)) { return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidGrant, ErrorDescription = "The user is no longer allowed to sign in." })); } // Create a new authentication ticket, but reuse the properties stored // in the refresh token, including the scopes originally granted. var ticket = await CreateTicketAsync(request, user, info.Properties); return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme)); } if (request.GrantType == "urn:ietf:params:oauth:grant-type:google_identity_token") { // Reject the request if the "assertion" parameter is missing. if (string.IsNullOrEmpty(request.Assertion)) { return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidRequest, ErrorDescription = "The mandatory 'assertion' parameter was missing." })); } // Create a new ClaimsIdentity containing the claims that // will be used to create an id_token and/or an access token. var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme); Console.WriteLine(identity.ToString()); Console.WriteLine(request.Code); var googleDetails = await GetGoogleDetailsAsync(request.Assertion); if (googleDetails != null) { // save //check to see if the ProviderId is already listed for this user var repeatUser = _ctx.Users .Where(x => x.ProviderId.Equals(googleDetails.ProviderUserId)) .FirstOrDefault(); //this signed in google user is not a repeat user and hasn't been saved yet if (repeatUser == null) { var result = await _userManager.CreateAsync( new ApplicationUser() { Email = googleDetails.Email, FirstName = googleDetails.FirstName, UserName = $"{googleDetails.Email.Split('@')[0]}_Google", FullName = googleDetails.Name, LastName = googleDetails.LastName, ProviderId = googleDetails.ProviderUserId, ProviderName = "GOOGLE", PictureUrl = "https://cdn.iconscout.com/public/images/icon/premium/png-512/gamer-games-video-casino-372bcf114ef0140a-512x512.png" }); if (!result.Succeeded) { AddErrors(result); return(BadRequest(result)); } else { _logger.LogInformation("Social User created a new account without password."); //var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); //var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme); //await _emailSender.SendEmailConfirmationAsync(model.Email, callbackUrl); //await _signInManager.SignInAsync(user, isPersistent: false); //_logger.LogInformation("User created a new account with password."); //return Ok(result); //return RedirectToLocal(returnUrl); } } } // Manually validate the identity token issued by Google, // including the issuer, the signature and the audience. // Then, copy the claims you need to the "identity" instance. identity.AddClaim(OpenIdConnectConstants.Claims.Subject, googleDetails.ProviderUserId, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim(OpenIdConnectConstants.Claims.Name, googleDetails.Name, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim(OpenIdConnectConstants.Claims.Email, googleDetails.Email, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim(OpenIdConnectConstants.Claims.GivenName, googleDetails.FirstName, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim(OpenIdConnectConstants.Claims.FamilyName, googleDetails.LastName, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim(OpenIdConnectConstants.Claims.Locale, googleDetails.Locale, OpenIdConnectConstants.Destinations.AccessToken); // Create a new authentication ticket holding the user identity. var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); // Then, copy the claims you need to the "identity" instance. ticket.SetScopes( OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.OfflineAccess, OpenIdConnectConstants.Scopes.Profile, OpenIdConnectConstants.Scopes.Email); return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme)); } if (request.GrantType == "urn:ietf:params:oauth:grant-type:facebook_access_token") { // Reject the request if the "assertion" parameter is missing. if (string.IsNullOrEmpty(request.Assertion)) { return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidRequest, ErrorDescription = "The mandatory 'assertion' parameter was missing." })); } // Create a new ClaimsIdentity containing the claims that // will be used to create an id_token and/or an access token. var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme); Console.WriteLine(identity.ToString()); Console.WriteLine(request.Code); var fbDetails = await GetFacebookDetailsAsync(request.Assertion); if (fbDetails != null) { // save //check to see if the ProviderId is already listed for this user var repeatUser = _ctx.Users .Where(x => x.ProviderId.Equals(fbDetails.ProviderUserId)) .FirstOrDefault(); // save if (repeatUser == null) { var result = await _userManager.CreateAsync( new ApplicationUser() { Email = fbDetails.Email, UserName = $"{fbDetails.Email.Split('@')[0]}_Facebook", FirstName = fbDetails.FirstName, FullName = fbDetails.Name, LastName = fbDetails.LastName, ProviderId = fbDetails.ProviderUserId, ProviderName = "FACEBOOK", PictureUrl = "https://cdn.iconscout.com/public/images/icon/premium/png-512/gamer-games-video-casino-372bcf114ef0140a-512x512.png" }); if (!result.Succeeded) { AddErrors(result); return(BadRequest(result)); } else { _logger.LogInformation("Social User created a new account without password."); //var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); //var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme); //await _emailSender.SendEmailConfirmationAsync(model.Email, callbackUrl); //await _signInManager.SignInAsync(user, isPersistent: false); //_logger.LogInformation("User created a new account with password."); //return Ok(result); //return RedirectToLocal(returnUrl); } } } // Manually validate the identity token issued by Google, // including the issuer, the signature and the audience. // Then, copy the claims you need to the "identity" instance. identity.AddClaim(OpenIdConnectConstants.Claims.Subject, fbDetails.ProviderUserId, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim(OpenIdConnectConstants.Claims.Name, fbDetails.Name, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim(OpenIdConnectConstants.Claims.Email, fbDetails.Email, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim(OpenIdConnectConstants.Claims.GivenName, fbDetails.FirstName, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim(OpenIdConnectConstants.Claims.FamilyName, fbDetails.LastName, OpenIdConnectConstants.Destinations.AccessToken); identity.AddClaim(OpenIdConnectConstants.Claims.Locale, fbDetails.Locale, OpenIdConnectConstants.Destinations.AccessToken); // Create a new authentication ticket holding the user identity. var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); // Then, copy the claims you need to the "identity" instance. ticket.SetScopes( OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.OfflineAccess, OpenIdConnectConstants.Scopes.Profile, OpenIdConnectConstants.Scopes.Email); return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme)); } return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.UnsupportedGrantType, ErrorDescription = "The specified grant type is not supported." })); }
public async Task <IActionResult> Accept(CancellationToken cancellationToken) { var response = HttpContext.GetOpenIdConnectResponse(); if (response != null) { return(BadRequest(response)); } var request = HttpContext.GetOpenIdConnectRequest(); if (request == null) { return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.ServerError, ErrorDescription = "Ha ocurrido un error interno." })); } Int32.TryParse(request.GetParameter("authuser").ToString(), out int authuser); var companyCode = request.GetParameter("company_code").ToString(); var user = User.Identities.ElementAtOrDefault(authuser); if (user == null) { return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.UnauthorizedClient, ErrorDescription = "No se encontro sesión del usuario." })); } if (!user.IsAuthenticated) { return(Unauthorized()); } try { var usuarioId = user.FindFirst(ClaimTypes.NameIdentifier).Value; var empresaId = await(companyCode.Length == 0 ? _repository.GetEmpresaIdAsync(usuarioId) : _repository.GetEmpresaIdAsync(usuarioId, companyCode)); string rol = await _repository.GetRolAsync(usuarioId); var usuario = await _repository.GetUsuarioPorIdAsync(usuarioId); var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme, OpenIdConnectConstants.Claims.Name, OpenIdConnectConstants.Claims.Role); identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "[unique id]"); identity.AddClaim("UsuarioId", usuarioId, OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); identity.AddClaim(OpenIdConnectConstants.Claims.Audience, "sigecoservices", OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); identity.AddClaim(ClaimTypes.Name, user.FindFirst(ClaimTypes.Name).Value, OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); identity.AddClaim(ClaimTypes.Role, rol, OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); identity.AddClaim("EmpresaId", empresaId.ToString(), OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); identity.AddClaim("ClienteId", request.ClientId.ToString(), OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); var props = new AuthenticationProperties(new Dictionary <string, string> { { "client_id", request.ClientId }, { "authuser", authuser.ToString() }, { "company_code", companyCode }, }); var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), props, OpenIdConnectServerDefaults.AuthenticationScheme); ticket.SetScopes(new[] { /* openid: */ OpenIdConnectConstants.Scopes.OpenId, /* email: */ OpenIdConnectConstants.Scopes.Email, /* profile: */ OpenIdConnectConstants.Scopes.Profile }.Intersect(request.GetScopes())); //Otorgamos acceso a aplicación var aplicacion = await _repository.GetAplicacionClienteAsync(request.ClientId, cancellationToken); if (aplicacion.EsTercero) { await _repository.AgregarUsuarioAplicacionAsync(usuarioId, request.ClientId); } // return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme)); } catch (AuthDomainException ex) { return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidRequest, ErrorDescription = ex.Message })); } }