public async Task <IActionResult> Create(CreateOpenIdApplicationViewModel model, string returnUrl = null)
        {
            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageApplications))
            {
                return(Forbid());
            }

            if (!string.IsNullOrEmpty(model.ClientSecret) &&
                string.Equals(model.Type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase))
            {
                ModelState.AddModelError(nameof(model.ClientSecret), S["No client secret can be set for public applications."]);
            }
            else if (string.IsNullOrEmpty(model.ClientSecret) &&
                     string.Equals(model.Type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase))
            {
                ModelState.AddModelError(nameof(model.ClientSecret), S["The client secret is required for confidential applications."]);
            }

            if (!string.IsNullOrEmpty(model.ClientId) && await _applicationManager.FindByClientIdAsync(model.ClientId) != null)
            {
                ModelState.AddModelError(nameof(model.ClientId), S["The client identifier is already taken by another application."]);
            }

            if (!ModelState.IsValid)
            {
                ViewData[nameof(OpenIdServerSettings)] = await GetServerSettingsAsync();

                ViewData["ReturnUrl"] = returnUrl;
                return(View(model));
            }

            var settings = new OpenIdApplicationSettings()
            {
                AllowAuthorizationCodeFlow = model.AllowAuthorizationCodeFlow,
                AllowClientCredentialsFlow = model.AllowClientCredentialsFlow,
                AllowHybridFlow            = model.AllowHybridFlow,
                AllowImplicitFlow          = model.AllowImplicitFlow,
                AllowLogoutEndpoint        = model.AllowLogoutEndpoint,
                AllowPasswordFlow          = model.AllowPasswordFlow,
                AllowRefreshTokenFlow      = model.AllowRefreshTokenFlow,
                ClientId               = model.ClientId,
                ClientSecret           = model.ClientSecret,
                ConsentType            = model.ConsentType,
                DisplayName            = model.DisplayName,
                PostLogoutRedirectUris = model.PostLogoutRedirectUris,
                RedirectUris           = model.RedirectUris,
                Roles  = model.RoleEntries.Where(x => x.Selected).Select(x => x.Name).ToArray(),
                Scopes = model.ScopeEntries.Where(x => x.Selected).Select(x => x.Name).ToArray(),
                Type   = model.Type
            };

            await _applicationManager.UpdateDescriptorFromSettings(settings);

            if (string.IsNullOrEmpty(returnUrl))
            {
                return(RedirectToAction(nameof(Index)));
            }

            return(this.LocalRedirect(returnUrl, true));
        }
        public async Task ExecuteAsync(RecipeExecutionContext context)
        {
            if (!string.Equals(context.Name, "OpenIdApplication", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            var model = context.Step.ToObject <OpenIdApplicationStepModel>();
            var app   = await _applicationManager.FindByClientIdAsync(model.ClientId);

            var settings = new OpenIdApplicationSettings()
            {
                AllowAuthorizationCodeFlow = model.AllowAuthorizationCodeFlow,
                AllowClientCredentialsFlow = model.AllowClientCredentialsFlow,
                AllowHybridFlow            = model.AllowHybridFlow,
                AllowImplicitFlow          = model.AllowImplicitFlow,
                AllowIntrospectionEndpoint = model.AllowIntrospectionEndpoint,
                AllowLogoutEndpoint        = model.AllowLogoutEndpoint,
                AllowPasswordFlow          = model.AllowPasswordFlow,
                AllowRefreshTokenFlow      = model.AllowRefreshTokenFlow,
                AllowRevocationEndpoint    = model.AllowRevocationEndpoint,
                ClientId               = model.ClientId,
                ClientSecret           = model.ClientSecret,
                ConsentType            = model.ConsentType,
                DisplayName            = model.DisplayName,
                PostLogoutRedirectUris = model.PostLogoutRedirectUris,
                RedirectUris           = model.RedirectUris,
                Roles  = model.RoleEntries.Select(x => x.Name).ToArray(),
                Scopes = model.ScopeEntries.Select(x => x.Name).ToArray(),
                Type   = model.Type,
                RequireProofKeyForCodeExchange = model.RequireProofKeyForCodeExchange,
            };

            await _applicationManager.UpdateDescriptorFromSettings(settings, app);
        }
Beispiel #3
0
        public async Task <IActionResult> Authorize(OpenIdConnectRequest request)
        {
            // Retrieve the claims stored in the authentication cookie.
            // If they can't be extracted, redirect the user to the login page.
            var result = await HttpContext.AuthenticateAsync();

            if (result == null || !result.Succeeded || request.HasPrompt(OpenIddictConstants.Prompts.Login))
            {
                return(RedirectToLoginPage(request));
            }

            // If a max_age parameter was provided, ensure that the cookie is not too old.
            // If it's too old, automatically redirect the user agent to the login page.
            if (request.MaxAge != null && result.Properties.IssuedUtc != null &&
                DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value))
            {
                return(RedirectToLoginPage(request));
            }

            var application = await _applicationManager.FindByClientIdAsync(request.ClientId);

            if (application == null)
            {
                return(View("Error", new ErrorViewModel
                {
                    Error = OpenIddictConstants.Errors.InvalidClient,
                    ErrorDescription = T["The specified 'client_id' parameter is invalid."]
                }));
            }

            var authorizations = await _authorizationManager.FindAsync(
                subject : _userManager.GetUserId(result.Principal),
                client : await _applicationManager.GetIdAsync(application),
                status : OpenIddictConstants.Statuses.Valid,
                type : OpenIddictConstants.AuthorizationTypes.Permanent,
                scopes : ImmutableArray.CreateRange(request.GetScopes()));

            switch (await _applicationManager.GetConsentTypeAsync(application))
            {
            case OpenIddictConstants.ConsentTypes.External when authorizations.IsEmpty:
                return(RedirectToClient(new OpenIdConnectResponse
                {
                    Error = OpenIddictConstants.Errors.ConsentRequired,
                    ErrorDescription = T["The logged in user is not allowed to access this client application."]
                }));

            case OpenIddictConstants.ConsentTypes.Implicit:
            case OpenIddictConstants.ConsentTypes.External when authorizations.Any():
            case OpenIddictConstants.ConsentTypes.Explicit when authorizations.Any() &&
                !request.HasPrompt(OpenIddictConstants.Prompts.Consent):
                return(await IssueTokensAsync(result.Principal, request, application, authorizations.LastOrDefault()));

            case OpenIddictConstants.ConsentTypes.Explicit when request.HasPrompt(OpenIddictConstants.Prompts.None):
                return(RedirectToClient(new OpenIdConnectResponse
                {
                    Error = OpenIddictConstants.Errors.ConsentRequired,
                    ErrorDescription = T["Interactive user consent is required."]
                }));

            default:
                return(View(new AuthorizeViewModel
                {
                    ApplicationName = await _applicationManager.GetDisplayNameAsync(application),
                    RequestId = request.RequestId,
                    Scope = request.Scope
                }));
            }
        }
        public async Task <IActionResult> Create(CreateOpenIdApplicationViewModel model, string returnUrl = null)
        {
            if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageApplications))
            {
                return(Unauthorized());
            }

            if (!string.IsNullOrEmpty(model.ClientSecret) &&
                string.Equals(model.Type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase))
            {
                ModelState.AddModelError(nameof(model.ClientSecret), T["No client secret can be set for public applications."]);
            }
            else if (string.IsNullOrEmpty(model.ClientSecret) &&
                     string.Equals(model.Type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase))
            {
                ModelState.AddModelError(nameof(model.ClientSecret), T["The client secret is required for confidential applications."]);
            }

            if (!string.IsNullOrEmpty(model.ClientId) && await _applicationManager.FindByClientIdAsync(model.ClientId) != null)
            {
                ModelState.AddModelError(nameof(model.ClientId), T["The client identifier is already taken by another application."]);
            }

            if (!ModelState.IsValid)
            {
                ViewData[nameof(OpenIdServerSettings)] = await GetServerSettingsAsync();

                ViewData["ReturnUrl"] = returnUrl;
                return(View(model));
            }

            var descriptor = new OpenIdApplicationDescriptor
            {
                ClientId     = model.ClientId,
                ClientSecret = model.ClientSecret,
                ConsentType  = model.ConsentType,
                DisplayName  = model.DisplayName,
                Type         = model.Type
            };

            if (model.AllowLogoutEndpoint)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout);
            }
            else
            {
                descriptor.Permissions.Remove(OpenIddictConstants.Permissions.Endpoints.Logout);
            }

            if (model.AllowAuthorizationCodeFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode);
            }
            if (model.AllowClientCredentialsFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials);
            }
            if (model.AllowImplicitFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit);
            }
            if (model.AllowPasswordFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password);
            }
            if (model.AllowRefreshTokenFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken);
            }
            if (model.AllowAuthorizationCodeFlow || model.AllowImplicitFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization);
            }
            if (model.AllowAuthorizationCodeFlow || model.AllowClientCredentialsFlow ||
                model.AllowPasswordFlow || model.AllowRefreshTokenFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token);
            }

            descriptor.PostLogoutRedirectUris.UnionWith(
                from uri in model.PostLogoutRedirectUris?.Split(new[] { " ", "," }, StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty <string>()
                select new Uri(uri, UriKind.Absolute));

            descriptor.RedirectUris.UnionWith(
                from uri in model.RedirectUris?.Split(new[] { " ", "," }, StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty <string>()
                select new Uri(uri, UriKind.Absolute));

            descriptor.Roles.UnionWith(model.RoleEntries
                                       .Where(role => role.Selected)
                                       .Select(role => role.Name));

            await _applicationManager.CreateAsync(descriptor);

            if (string.IsNullOrEmpty(returnUrl))
            {
                return(RedirectToAction("Index"));
            }

            return(LocalRedirect(returnUrl));
        }
Beispiel #5
0
        public async Task <IActionResult> Authorize()
        {
            var response = HttpContext.GetOpenIddictServerResponse();

            if (response != null)
            {
                return(View("Error", new ErrorViewModel
                {
                    Error = response.Error,
                    ErrorDescription = response.ErrorDescription
                }));
            }

            var request = HttpContext.GetOpenIddictServerRequest();

            if (request == null)
            {
                return(NotFound());
            }

            // Retrieve the claims stored in the authentication cookie.
            // If they can't be extracted, redirect the user to the login page.
            var result = await HttpContext.AuthenticateAsync();

            if (result == null || !result.Succeeded || request.HasPrompt(Prompts.Login))
            {
                return(RedirectToLoginPage(request));
            }

            // If a max_age parameter was provided, ensure that the cookie is not too old.
            // If it's too old, automatically redirect the user agent to the login page.
            if (request.MaxAge != null && result.Properties.IssuedUtc != null &&
                DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value))
            {
                return(RedirectToLoginPage(request));
            }

            var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ??
                              throw new InvalidOperationException("The application details cannot be found.");

            var authorizations = await _authorizationManager.FindAsync(
                subject : result.Principal.GetUserIdentifier(),
                client : await _applicationManager.GetIdAsync(application),
                status : Statuses.Valid,
                type : AuthorizationTypes.Permanent,
                scopes : request.GetScopes()).ToListAsync();

            switch (await _applicationManager.GetConsentTypeAsync(application))
            {
            case ConsentTypes.External when !authorizations.Any():
                return(Forbid(new AuthenticationProperties(new Dictionary <string, string>
                {
                    [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired,
                    [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
                        S["The logged in user is not allowed to access this client application."]
                }), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));

            case ConsentTypes.Implicit:
            case ConsentTypes.External when authorizations.Any():
            case ConsentTypes.Explicit when authorizations.Any() && !request.HasPrompt(Prompts.Consent):
                var identity = new ClaimsIdentity(result.Principal.Claims, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);

                var principal = new ClaimsPrincipal(identity);

                identity.AddClaim(OpenIdConstants.Claims.EntityType, OpenIdConstants.EntityTypes.User,
                                  Destinations.AccessToken, Destinations.IdentityToken);

                // Note: while ASP.NET Core Identity uses the legacy WS-Federation claims (exposed by the ClaimTypes class),
                // OpenIddict uses the newer JWT claims defined by the OpenID Connect specification. To ensure the mandatory
                // subject claim is correctly populated (and avoid an InvalidOperationException), it's manually added here.
                if (string.IsNullOrEmpty(result.Principal.FindFirst(Claims.Subject)?.Value))
                {
                    identity.AddClaim(new Claim(Claims.Subject, result.Principal.GetUserIdentifier()));
                }

                principal.SetScopes(request.GetScopes());
                principal.SetResources(await GetResourcesAsync(request.GetScopes()));

                // Automatically create a permanent authorization to avoid requiring explicit consent
                // for future authorization or token requests containing the same scopes.
                var authorization = authorizations.LastOrDefault();
                if (authorization == null)
                {
                    authorization = await _authorizationManager.CreateAsync(
                        principal : principal,
                        subject : principal.GetUserIdentifier(),
                        client : await _applicationManager.GetIdAsync(application),
                        type : AuthorizationTypes.Permanent,
                        scopes : principal.GetScopes());
                }

                principal.SetAuthorizationId(await _authorizationManager.GetIdAsync(authorization));

                foreach (var claim in principal.Claims)
                {
                    claim.SetDestinations(GetDestinations(claim, principal));
                }

                return(SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));

            case ConsentTypes.Explicit when request.HasPrompt(Prompts.None):
                return(Forbid(new AuthenticationProperties(new Dictionary <string, string>
                {
                    [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired,
                    [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
                        S["Interactive user consent is required."]
                }), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));

            default:
                return(View(new AuthorizeViewModel
                {
                    ApplicationName = await _applicationManager.GetLocalizedDisplayNameAsync(application),
                    RequestId = request.RequestId,
                    Scope = request.Scope
                }));
            }

            IActionResult RedirectToLoginPage(OpenIddictRequest request)
            {
                // If the client application requested promptless authentication,
                // return an error indicating that the user is not logged in.
                if (request.HasPrompt(Prompts.None))
                {
                    return(Forbid(new AuthenticationProperties(new Dictionary <string, string>
                    {
                        [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
                        [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
                            S["The user is not logged in."]
                    }), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
                }

                string GetRedirectUrl()
                {
                    // Override the prompt parameter to prevent infinite authentication/authorization loops.
                    var parameters = Request.Query.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

                    parameters[Parameters.Prompt] = "continue";

                    return(Request.PathBase + Request.Path + QueryString.Create(parameters));
                }

                return(Challenge(new AuthenticationProperties
                {
                    RedirectUri = GetRedirectUrl()
                }));
            }
        }
Beispiel #6
0
        public async Task ExecuteAsync(RecipeExecutionContext context)
        {
            if (!string.Equals(context.Name, "OpenIdApplication", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            var model = context.Step.ToObject <OpenIdApplicationStepModel>();
            var app   = await _applicationManager.FindByClientIdAsync(model.ClientId);

            var descriptor = new OpenIdApplicationDescriptor();
            var isNew      = true;

            if (app != null)
            {
                isNew = false;
                await _applicationManager.PopulateAsync(app, descriptor);
            }

            descriptor.ClientId     = model.ClientId;
            descriptor.ClientSecret = model.ClientSecret;
            descriptor.ConsentType  = model.ConsentType;
            descriptor.DisplayName  = model.DisplayName;
            descriptor.Type         = model.Type;

            if (model.AllowAuthorizationCodeFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode);
            }
            if (model.AllowClientCredentialsFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials);
            }
            if (model.AllowImplicitFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit);
            }
            if (model.AllowPasswordFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password);
            }
            if (model.AllowRefreshTokenFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken);
            }
            if (model.AllowAuthorizationCodeFlow || model.AllowImplicitFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization);
            }
            if (model.AllowLogoutEndpoint)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout);
            }
            if (model.AllowAuthorizationCodeFlow || model.AllowClientCredentialsFlow ||
                model.AllowPasswordFlow || model.AllowRefreshTokenFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token);
            }
            if (model.AllowAuthorizationCodeFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Code);
            }
            if (model.AllowImplicitFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdToken);

                if (string.Equals(model.Type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase))
                {
                    descriptor.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken);
                    descriptor.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Token);
                }
            }
            if (model.AllowHybridFlow)
            {
                descriptor.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken);

                if (string.Equals(model.Type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase))
                {
                    descriptor.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken);
                    descriptor.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeToken);
                }
            }
            if (!string.IsNullOrWhiteSpace(model.PostLogoutRedirectUris))
            {
                descriptor.PostLogoutRedirectUris.UnionWith(
                    model.PostLogoutRedirectUris
                    .Split(' ', StringSplitOptions.RemoveEmptyEntries)
                    .Select(u => new Uri(u, UriKind.Absolute)));
            }
            if (!string.IsNullOrWhiteSpace(model.RedirectUris))
            {
                descriptor.RedirectUris.UnionWith(
                    model.RedirectUris
                    .Split(' ', StringSplitOptions.RemoveEmptyEntries)
                    .Select(u => new Uri(u, UriKind.Absolute)));
            }
            if (model.RoleEntries != null)
            {
                descriptor.Roles.UnionWith(
                    model.RoleEntries
                    .Select(role => role.Name));
            }
            if (model.ScopeEntries != null)
            {
                descriptor.Permissions.UnionWith(
                    model.ScopeEntries
                    .Select(scope => OpenIddictConstants.Permissions.Prefixes.Scope + scope.Name));
            }
            if (isNew)
            {
                await _applicationManager.CreateAsync(descriptor);
            }
            else
            {
                await _applicationManager.UpdateAsync(app, descriptor);
            }
        }