private static async Task<OpenIdConnectConfiguration> GetOpenIdConnectConfigurationAsync(RedirectContext context, string defaultPolicy)
 {
     var manager = (PolicyConfigurationManager)context.Options.ConfigurationManager;
     var policy = context.Properties.Items.ContainsKey(AuthenticationConstants.B2CPolicy) ? context.Properties.Items[AuthenticationConstants.B2CPolicy] : defaultPolicy;
     var configuration = await manager.GetConfigurationByPolicyAsync(CancellationToken.None, policy);
     return configuration;
 }
        private async Task OnRedirectToIdentityProviderForSignOut(RedirectContext context)
        {
            AzureAdSettings azureADSettings = GetAdSettings(context);
            var configuration = await GetOpenIdConnectConfigurationAsync(context, azureADSettings.B2CPolicySettings.SignInOrSignUpPolicy);
            context.ProtocolMessage.IssuerAddress = configuration.EndSessionEndpoint;

        }
        /// <summary>
        /// Called prior to the OIDC middleware redirecting to the authentication endpoint.  In the event we are signing up a tenant, we need to
        /// put the "admin_consent" value for the prompt query string parameter.  AAD uses this to show the admin consent flow.
        /// </summary>
        /// <param name="context">The <see cref="Microsoft.AspNetCore.Authentication.OpenIdConnect.RedirectContext"/> for this event.</param>
        /// <returns>A completed <see cref="System.Threading.Tasks.Task"/></returns>
        public override Task RedirectToIdentityProvider(RedirectContext context)
        {
            if (context.IsSigningUp())
            {
                context.ProtocolMessage.Prompt = "admin_consent";
            }

            _logger.RedirectToIdentityProvider();
            return Task.FromResult(0);
        }
        internal static Task RedirectToIdentityProvider(RedirectContext context)
        {
            eventsFired.Add(nameof(RedirectToIdentityProvider));

            if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
            {
                context.ProtocolMessage.PostLogoutRedirectUri =
                    context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + new PathString("/Account/Login");
            }

            return Task.FromResult(0);
        }
Example #5
0
 private static Task Redirect(IConfiguration configuration,
                              Microsoft.AspNetCore.Authentication.OpenIdConnect.RedirectContext ctx)
 {
     //ctx.ProtocolMessage.RedirectUri = String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}{1}", configuration.GetValue<String>(ConfigurationSectionKeys.RedirectHost), configuration.GetValue<String>("AzureAd:CallbackPath"));
     return(Task.CompletedTask);
 }
Example #6
0
 /// <summary>
 /// Invoked before redirecting to the identity provider to sign out.
 /// </summary>
 public virtual Task RedirectToIdentityProviderForSignOut(RedirectContext context) => OnRedirectToIdentityProviderForSignOut(context);
Example #7
0
 /// <summary>
 /// Invoked before redirecting to the identity provider to authenticate. This can be used to set ProtocolMessage.State
 /// that will be persisted through the authentication process. The ProtocolMessage can also be used to add or customize
 /// parameters sent to the identity provider.
 /// </summary>
 public virtual Task RedirectToIdentityProvider(RedirectContext context) => OnRedirectToIdentityProvider(context);
        /// <summary>
        /// Handles Signout
        /// </summary>
        /// <returns></returns>
        protected override async Task HandleSignOutAsync(SignOutContext signout)
        {
            if (signout != null)
            {
                if (_configuration == null && Options.ConfigurationManager != null)
                {
                    _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted);
                }

                var message = new OpenIdConnectMessage()
                {
                    IssuerAddress = _configuration == null ? string.Empty : (_configuration.EndSessionEndpoint ?? string.Empty),
                };

                // Set End_Session_Endpoint in order:
                // 1. properties.Redirect
                // 2. Options.PostLogoutRedirectUri
                var properties        = new AuthenticationProperties(signout.Properties);
                var logoutRedirectUri = properties.RedirectUri;
                if (!string.IsNullOrEmpty(logoutRedirectUri))
                {
                    // Relative to PathBase
                    if (logoutRedirectUri.StartsWith("/", StringComparison.Ordinal))
                    {
                        logoutRedirectUri = BuildRedirectUri(logoutRedirectUri);
                    }
                    message.PostLogoutRedirectUri = logoutRedirectUri;
                }
                else if (!string.IsNullOrEmpty(Options.PostLogoutRedirectUri))
                {
                    logoutRedirectUri = Options.PostLogoutRedirectUri;
                    // Relative to PathBase
                    if (logoutRedirectUri.StartsWith("/", StringComparison.Ordinal))
                    {
                        logoutRedirectUri = BuildRedirectUri(logoutRedirectUri);
                    }
                    message.PostLogoutRedirectUri = logoutRedirectUri;
                }

                message.IdTokenHint = await Context.Authentication.GetTokenAsync(OpenIdConnectParameterNames.IdToken);

                var redirectContext = new RedirectContext(Context, Options, properties)
                {
                    ProtocolMessage = message
                };

                await Options.Events.RedirectToIdentityProviderForSignOut(redirectContext);

                if (redirectContext.HandledResponse)
                {
                    Logger.RedirectToIdentityProviderForSignOutHandledResponse();
                    return;
                }
                else if (redirectContext.Skipped)
                {
                    Logger.RedirectToIdentityProviderForSignOutSkipped();
                    return;
                }

                message = redirectContext.ProtocolMessage;

                if (Options.AuthenticationMethod == OpenIdConnectRedirectBehavior.RedirectGet)
                {
                    var redirectUri = message.CreateLogoutRequestUrl();
                    if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute))
                    {
                        Logger.InvalidLogoutQueryStringRedirectUrl(redirectUri);
                    }

                    Response.Redirect(redirectUri);
                }
                else if (Options.AuthenticationMethod == OpenIdConnectRedirectBehavior.FormPost)
                {
                    var inputs = new StringBuilder();
                    foreach (var parameter in message.Parameters)
                    {
                        var name  = HtmlEncoder.Encode(parameter.Key);
                        var value = HtmlEncoder.Encode(parameter.Value);

                        var input = string.Format(CultureInfo.InvariantCulture, InputTagFormat, name, value);
                        inputs.AppendLine(input);
                    }

                    var issuer = HtmlEncoder.Encode(message.IssuerAddress);

                    var content = string.Format(CultureInfo.InvariantCulture, HtmlFormFormat, issuer, inputs);
                    var buffer  = Encoding.UTF8.GetBytes(content);

                    Response.ContentLength = buffer.Length;
                    Response.ContentType   = "text/html;charset=UTF-8";

                    // Emit Cache-Control=no-cache to prevent client caching.
                    Response.Headers[HeaderNames.CacheControl] = "no-cache";
                    Response.Headers[HeaderNames.Pragma]       = "no-cache";
                    Response.Headers[HeaderNames.Expires]      = "-1";

                    await Response.Body.WriteAsync(buffer, 0, buffer.Length);
                }
            }
        }
        /// <summary>
        /// Responds to a 401 Challenge. Sends an OpenIdConnect message to the 'identity authority' to obtain an identity.
        /// </summary>
        /// <returns></returns>
        protected override async Task <bool> HandleUnauthorizedAsync(ChallengeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            Logger.EnteringOpenIdAuthenticationHandlerHandleUnauthorizedAsync(GetType().FullName);

            // order for local RedirectUri
            // 1. challenge.Properties.RedirectUri
            // 2. CurrentUri if RedirectUri is not set)
            var properties = new AuthenticationProperties(context.Properties)
            {
                ExpiresUtc = Options.SystemClock.UtcNow.Add(Options.RemoteAuthenticationTimeout)
            };

            if (string.IsNullOrEmpty(properties.RedirectUri))
            {
                properties.RedirectUri = CurrentUri;
            }
            Logger.PostAuthenticationLocalRedirect(properties.RedirectUri);

            if (_configuration == null && Options.ConfigurationManager != null)
            {
                _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted);
            }

            var message = new OpenIdConnectMessage
            {
                ClientId      = Options.ClientId,
                IssuerAddress = _configuration?.AuthorizationEndpoint ?? string.Empty,
                RedirectUri   = BuildRedirectUri(Options.CallbackPath),
                Resource      = Options.Resource,
                ResponseType  = Options.ResponseType,
                Scope         = string.Join(" ", Options.Scope)
            };

            // Omitting the response_mode parameter when it already corresponds to the default
            // response_mode used for the specified response_type is recommended by the specifications.
            // See http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#ResponseModes
            if (!string.Equals(Options.ResponseType, OpenIdConnectResponseTypes.Code, StringComparison.Ordinal) ||
                !string.Equals(Options.ResponseMode, OpenIdConnectResponseModes.Query, StringComparison.Ordinal))
            {
                message.ResponseMode = Options.ResponseMode;
            }

            if (Options.ProtocolValidator.RequireNonce)
            {
                message.Nonce = Options.ProtocolValidator.GenerateNonce();
                WriteNonceCookie(message.Nonce);
            }

            GenerateCorrelationId(properties);

            var redirectContext = new RedirectContext(Context, Options, properties)
            {
                ProtocolMessage = message
            };

            await Options.Events.RedirectToIdentityProvider(redirectContext);

            if (redirectContext.HandledResponse)
            {
                Logger.RedirectToIdentityProviderHandledResponse();
                return(true);
            }
            else if (redirectContext.Skipped)
            {
                Logger.RedirectToIdentityProviderSkipped();
                return(false);
            }

            message = redirectContext.ProtocolMessage;

            if (!string.IsNullOrEmpty(message.State))
            {
                properties.Items[OpenIdConnectDefaults.UserstatePropertiesKey] = message.State;
            }

            // When redeeming a 'code' for an AccessToken, this value is needed
            properties.Items.Add(OpenIdConnectDefaults.RedirectUriForCodePropertiesKey, message.RedirectUri);

            message.State = Options.StateDataFormat.Protect(properties);

            if (Options.AuthenticationMethod == OpenIdConnectRedirectBehavior.RedirectGet)
            {
                var redirectUri = message.CreateAuthenticationRequestUrl();
                if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute))
                {
                    Logger.InvalidAuthenticationRequestUrl(redirectUri);
                }

                Response.Redirect(redirectUri);
                return(true);
            }
            else if (Options.AuthenticationMethod == OpenIdConnectRedirectBehavior.FormPost)
            {
                var inputs = new StringBuilder();
                foreach (var parameter in message.Parameters)
                {
                    var name  = HtmlEncoder.Encode(parameter.Key);
                    var value = HtmlEncoder.Encode(parameter.Value);

                    var input = string.Format(CultureInfo.InvariantCulture, InputTagFormat, name, value);
                    inputs.AppendLine(input);
                }

                var issuer = HtmlEncoder.Encode(message.IssuerAddress);

                var content = string.Format(CultureInfo.InvariantCulture, HtmlFormFormat, issuer, inputs);
                var buffer  = Encoding.UTF8.GetBytes(content);

                Response.ContentLength = buffer.Length;
                Response.ContentType   = "text/html;charset=UTF-8";

                // Emit Cache-Control=no-cache to prevent client caching.
                Response.Headers[HeaderNames.CacheControl] = "no-cache";
                Response.Headers[HeaderNames.Pragma]       = "no-cache";
                Response.Headers[HeaderNames.Expires]      = "-1";

                await Response.Body.WriteAsync(buffer, 0, buffer.Length);

                return(true);
            }

            throw new NotImplementedException($"An unsupported authentication method has been configured: {Options.AuthenticationMethod}");
        }
Example #10
0
 public virtual Task RedirectToIdentityProviderForSignOut(RedirectContext context) => OnRedirectToIdentityProviderForSignOut(context);
Example #11
0
 public virtual Task RedirectToIdentityProvider(RedirectContext context) => OnRedirectToIdentityProvider(context);