예제 #1
0
 private static Task AuthenticationFailed(
     AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
 {
     context.OwinContext.Response.Redirect("/Home/Error?message=" + context.Exception.Message);
     context.HandleResponse(); // Suppress the exception
     return Task.FromResult(0);
 }
 private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
 {
     notification.HandleResponse();
     notification.Response.Redirect("/Home/Error?message=" + notification.Exception.Message);
     return Task.FromResult(0);
 }
        protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
        {
            if (Options.CallbackPath.HasValue && Options.CallbackPath != (Request.PathBase + Request.Path))
            {
                return null;
            }

            OpenIdConnectMessage openIdConnectMessage = null;

            if (string.Equals(Request.Method, "POST", StringComparison.OrdinalIgnoreCase)
              && !string.IsNullOrWhiteSpace(Request.ContentType)
              && Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)
              && Request.Body.CanRead)
            {
                if (!Request.Body.CanSeek)
                {
                    _logger.WriteVerbose("Buffering request body");
                    MemoryStream memoryStream = new MemoryStream();
                    await Request.Body.CopyToAsync(memoryStream);
                    memoryStream.Seek(0, SeekOrigin.Begin);
                    Request.Body = memoryStream;
                }

                IFormCollection form = await Request.ReadFormAsync();
                Request.Body.Seek(0, SeekOrigin.Begin);

                openIdConnectMessage = new OpenIdConnectMessage(form);
            }

            if (openIdConnectMessage == null)
            {
                return null;
            }

            ExceptionDispatchInfo authFailedEx = null;
            string policy = string.Empty;
            try
            {
                var messageReceivedNotification = new MessageReceivedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = openIdConnectMessage
                };
                await Options.Notifications.MessageReceived(messageReceivedNotification);
                if (messageReceivedNotification.HandledResponse)
                {
                    return GetHandledResponseTicket();
                }
                if (messageReceivedNotification.Skipped)
                {
                    return null;
                }

                AuthenticationProperties properties = GetPropertiesFromState(openIdConnectMessage.State);
                if (properties == null)
                {
                    _logger.WriteWarning("The state field is missing or invalid.");
                    return null;
                }

                string nonce = null;
                if (Options.ProtocolValidator.RequireNonce)
                {
                    nonce = RetrieveNonce(openIdConnectMessage);
                }

                if (!string.IsNullOrWhiteSpace(openIdConnectMessage.Error))
                {
                    throw new OpenIdConnectProtocolException(
                        string.Format(CultureInfo.InvariantCulture,
                                      openIdConnectMessage.Error,
                                      "", openIdConnectMessage.ErrorDescription ?? string.Empty, openIdConnectMessage.ErrorUri ?? string.Empty));
                }

                if (string.IsNullOrWhiteSpace(openIdConnectMessage.IdToken))
                {
                    _logger.WriteWarning("The id_token is missing.");
                    return null;
                }

                var securityTokenReceivedNotification = new SecurityTokenReceivedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = openIdConnectMessage,
                };
                await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification);
                if (securityTokenReceivedNotification.HandledResponse)
                {
                    return GetHandledResponseTicket();
                }
                if (securityTokenReceivedNotification.Skipped)
                {
                    return null;
                }

                // Enable Per-Policy Metadata Retreival
                if (properties.Dictionary.TryGetValue(PolicyParameter, out policy))
                {
                    B2CConfigurationManager mgr = Options.ConfigurationManager as B2CConfigurationManager;
                    _configuration = await mgr.GetConfigurationAsync(Context.Request.CallCancelled, policy);
                }
                else
                {
                    _logger.WriteWarning("No policy identifier was found in the Authentication Properties of the request.");
                    return null;
                }

                TokenValidationParameters tvp = Options.TokenValidationParameters.Clone();
                IEnumerable<string> issuers = new[] { _configuration.Issuer };
                tvp.ValidIssuers = (tvp.ValidIssuers == null ? issuers : tvp.ValidIssuers.Concat(issuers));
                tvp.IssuerSigningTokens = (tvp.IssuerSigningTokens == null ? _configuration.SigningTokens : tvp.IssuerSigningTokens.Concat(_configuration.SigningTokens));

                SecurityToken validatedToken;
                ClaimsPrincipal principal = Options.SecurityTokenHandlers.ValidateToken(openIdConnectMessage.IdToken, tvp, out validatedToken);
                ClaimsIdentity claimsIdentity = principal.Identity as ClaimsIdentity;

                JwtSecurityToken jwt = validatedToken as JwtSecurityToken;
                AuthenticationTicket ticket = new AuthenticationTicket(claimsIdentity, properties);

                if (!string.IsNullOrWhiteSpace(openIdConnectMessage.SessionState))
                {
                    ticket.Properties.Dictionary[OpenIdConnectSessionProperties.SessionState] = openIdConnectMessage.SessionState;
                }

                if (!string.IsNullOrWhiteSpace(_configuration.CheckSessionIframe))
                {
                    ticket.Properties.Dictionary[OpenIdConnectSessionProperties.CheckSessionIFrame] = _configuration.CheckSessionIframe;
                }

                if (Options.UseTokenLifetime)
                {
                    DateTime issued = jwt.ValidFrom;
                    if (issued != DateTime.MinValue)
                    {
                        ticket.Properties.IssuedUtc = issued.ToUniversalTime();
                    }
                    DateTime expires = jwt.ValidTo;
                    if (expires != DateTime.MinValue)
                    {
                        ticket.Properties.ExpiresUtc = expires.ToUniversalTime();
                    }
                    ticket.Properties.AllowRefresh = false;
                }

                var securityTokenValidatedNotification = new SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options)
                {
                    AuthenticationTicket = ticket,
                    ProtocolMessage = openIdConnectMessage,
                };
                await Options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification);
                if (securityTokenValidatedNotification.HandledResponse)
                {
                    return GetHandledResponseTicket();
                }
                if (securityTokenValidatedNotification.Skipped)
                {
                    return null;
                }
                ticket = securityTokenValidatedNotification.AuthenticationTicket;

                var protocolValidationContext = new OpenIdConnectProtocolValidationContext
                {
                    AuthorizationCode = openIdConnectMessage.Code,
                    Nonce = nonce,
                };

                Options.ProtocolValidator.Validate(jwt, protocolValidationContext);
                if (openIdConnectMessage.Code != null)
                {
                    var authorizationCodeReceivedNotification = new AuthorizationCodeReceivedNotification(Context, Options)
                    {
                        AuthenticationTicket = ticket,
                        Code = openIdConnectMessage.Code,
                        JwtSecurityToken = jwt,
                        ProtocolMessage = openIdConnectMessage,
                        RedirectUri = ticket.Properties.Dictionary.ContainsKey(OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey) ?
                            ticket.Properties.Dictionary[OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey] : string.Empty,
                    };
                    await Options.Notifications.AuthorizationCodeReceived(authorizationCodeReceivedNotification);
                    if (authorizationCodeReceivedNotification.HandledResponse)
                    {
                        return GetHandledResponseTicket();
                    }
                    if (authorizationCodeReceivedNotification.Skipped)
                    {
                        return null;
                    }
                    ticket = authorizationCodeReceivedNotification.AuthenticationTicket;
                }

                return ticket;
            }
            catch (Exception exception)
            {
                authFailedEx = ExceptionDispatchInfo.Capture(exception);
            }

            if (authFailedEx != null)
            {
                _logger.WriteError("Exception occurred while processing message: '" + authFailedEx.ToString());

                if (Options.RefreshOnIssuerKeyNotFound && authFailedEx.SourceException.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException)))
                {
                    B2CConfigurationManager mgr = Options.ConfigurationManager as B2CConfigurationManager;
                    mgr.RequestRefresh(policy);
                }

                var authenticationFailedNotification = new AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = openIdConnectMessage,
                    Exception = authFailedEx.SourceException
                };
                await Options.Notifications.AuthenticationFailed(authenticationFailedNotification);
                if (authenticationFailedNotification.HandledResponse)
                {
                    return GetHandledResponseTicket();
                }
                if (authenticationFailedNotification.Skipped)
                {
                    return null;
                }

                authFailedEx.Throw();
            }

            return null;
        }
예제 #4
0
        // If the javascript issues an OIDC authorize request, and it fails (meaning the user needs to login)
        // this notification will be triggered with the error message 'login_required'
        public static Task AuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
        {
            string cookieStateValue = null;
            ICookieManager cookieManager = new ChunkingCookieManager();
            string cookie = cookieManager.GetRequestCookie(notification.OwinContext, CookieName);
            AuthenticationTicket ticket = ticketDataFormat.Unprotect(cookie);
            if (ticket.Properties.Dictionary != null)
                ticket.Properties.Dictionary.TryGetValue(OpenIdConnectAuthenticationDefaults.AuthenticationType + "SingleSignOut", out cookieStateValue);

            // If the failed authentication was a result of a request by the SingleSignOut javascript
            if (cookieStateValue != null && cookieStateValue.Contains(notification.ProtocolMessage.State) && notification.Exception.Message == "login_required");
            {
                // Clear the SingleSignOut cookie, and clear the OIDC session state so 
                //that we don't see any further "Session Changed" messages from the iframe.
                ticket.Properties.Dictionary[OpenIdConnectSessionProperties.SessionState] = "";
                ticket.Properties.Dictionary[OpenIdConnectAuthenticationDefaults.AuthenticationType + "SingleSignOut"] = "";
                cookieManager.AppendResponseCookie(notification.OwinContext, CookieName, ticketDataFormat.Protect(ticket), new CookieOptions());
                
                notification.Response.Redirect("Account/SingleSignOut");
                notification.HandleResponse();
            }

            return Task.FromResult<object>(null);
        }
예제 #5
0
        /// <summary>
        /// Invokes the login procedure (2nd leg of SP-Initiated login). Analagous to Saml20SignonHandler from ASP.Net DLL
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task<AuthenticationTicket> Invoke(IOwinContext context)
        {
            Logger.Debug(TraceMessages.SignOnHandlerCalled);
            ExceptionDispatchInfo authFailedEx = null;
            try {
                var messageReceivedNotification = new MessageReceivedNotification<SamlMessage, SamlAuthenticationOptions>(context, options)
                {
                    ProtocolMessage = new SamlMessage(context, configuration, null)
                };
                await options.Notifications.MessageReceived(messageReceivedNotification);
                if (messageReceivedNotification.HandledResponse) {
                    return null; // GetHandledResponseTicket()
                }
                if (messageReceivedNotification.Skipped) {
                    return null;
                }
                var requestParams = await HandleResponse(context);
                var assertion = context.Get<Saml20Assertion>("Saml2:assertion");
                var securityTokenReceivedNotification = new SecurityTokenReceivedNotification<SamlMessage, SamlAuthenticationOptions>(context, options)
                {
                    ProtocolMessage = new SamlMessage(context, configuration, assertion)
                };
                await options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification);
                if (securityTokenReceivedNotification.HandledResponse) {
                    return null; // GetHandledResponseTicket();
                }
                if (securityTokenReceivedNotification.Skipped) {
                    return null;
                }

                var ticket = await GetAuthenticationTicket(context, requestParams);

                var securityTokenValidatedNotification = new SecurityTokenValidatedNotification<SamlMessage, SamlAuthenticationOptions>(context, options)
                {
                    AuthenticationTicket = ticket,
                    ProtocolMessage = new SamlMessage(context, configuration, assertion)
                };

                await options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification);
                if (securityTokenValidatedNotification.HandledResponse) {
                    return null; // GetHandledResponseTicket();
                }
                if (securityTokenValidatedNotification.Skipped) {
                    return null; // null;
                }
                // Flow possible changes
                ticket = securityTokenValidatedNotification.AuthenticationTicket;

                context.Authentication.AuthenticationResponseGrant = new AuthenticationResponseGrant(ticket.Identity, ticket.Properties);                
                return ticket;
            }
            catch (Exception ex) {
                authFailedEx = ExceptionDispatchInfo.Capture(ex);
            }
            if (authFailedEx != null) {
                Logger.Error("Exception occurred while processing message: " + authFailedEx.SourceException);
                var message = new SamlMessage(context, configuration, context.Get<Saml20Assertion>("Saml2:assertion"));
                var authenticationFailedNotification = new AuthenticationFailedNotification<SamlMessage, SamlAuthenticationOptions>(context, options)
                {
                    ProtocolMessage = message,
                    Exception = authFailedEx.SourceException
                };
                await options.Notifications.AuthenticationFailed(authenticationFailedNotification);
                if (authenticationFailedNotification.HandledResponse) {
                    return null;//GetHandledResponseTicket();
                }
                if (authenticationFailedNotification.Skipped) {
                    return null; //null
                }

                authFailedEx.Throw();
            }
            return null;
        }
예제 #6
0
 private Task AuthFailed(AuthenticationFailedNotification <Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> arg)
 {
     arg.Response.Redirect(string.Format("/home?msg=", arg.Exception.Message));
     return(Task.FromResult(0));
 }
 private Task OnAuthenticationFailed(AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
 {
     context.HandleResponse();
     context.Response.Redirect("/Home/Error?message=" + context.Exception.Message);
     return(Task.FromResult(0));
 }
        /// <summary>
        /// Invoked to process incoming authentication messages.
        /// </summary>
        /// <returns></returns>
        protected override async Task <AuthenticationTicket> AuthenticateCoreAsync()
        {
            // Allow login to be constrained to a specific path.
            if (Options.CallbackPath.HasValue && Options.CallbackPath != (Request.PathBase + Request.Path))
            {
                return(null);
            }

            WsFederationMessage wsFederationMessage = null;

            // assumption: if the ContentType is "application/x-www-form-urlencoded" it should be safe to read as it is small.
            if (string.Equals(Request.Method, "POST", StringComparison.OrdinalIgnoreCase) &&
                !string.IsNullOrWhiteSpace(Request.ContentType)
                // May have media/type; charset=utf-8, allow partial match.
                && Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) &&
                Request.Body.CanRead)
            {
                if (!Request.Body.CanSeek)
                {
                    _logger.WriteVerbose("Buffering request body");
                    // Buffer in case this body was not meant for us.
                    MemoryStream memoryStream = new MemoryStream();
                    await Request.Body.CopyToAsync(memoryStream);

                    memoryStream.Seek(0, SeekOrigin.Begin);
                    Request.Body = memoryStream;
                }
                IFormCollection form = await Request.ReadFormAsync();

                Request.Body.Seek(0, SeekOrigin.Begin);

                // TODO: a delegate on WsFederationAuthenticationOptions would allow for users to hook their own custom message.
                wsFederationMessage = new WsFederationMessage(form);
            }

            if (wsFederationMessage == null || !wsFederationMessage.IsSignInMessage)
            {
                return(null);
            }

            ExceptionDispatchInfo authFailedEx = null;

            try
            {
                var messageReceivedNotification = new MessageReceivedNotification <WsFederationMessage, WsFederationAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = wsFederationMessage
                };
                await Options.Notifications.MessageReceived(messageReceivedNotification);

                if (messageReceivedNotification.HandledResponse)
                {
                    return(GetHandledResponseTicket());
                }
                if (messageReceivedNotification.Skipped)
                {
                    return(null);
                }

                if (wsFederationMessage.Wresult == null)
                {
                    _logger.WriteWarning("Received a sign-in message without a WResult.");
                    return(null);
                }

                string token = wsFederationMessage.GetToken();
                if (string.IsNullOrWhiteSpace(token))
                {
                    _logger.WriteWarning("Received a sign-in message without a token.");
                    return(null);
                }

                var securityTokenReceivedNotification = new SecurityTokenReceivedNotification <WsFederationMessage, WsFederationAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = wsFederationMessage
                };
                await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification);

                if (securityTokenReceivedNotification.HandledResponse)
                {
                    return(GetHandledResponseTicket());
                }
                if (securityTokenReceivedNotification.Skipped)
                {
                    return(null);
                }

                if (_configuration == null)
                {
                    _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.Request.CallCancelled);
                }

                // Copy and augment to avoid cross request race conditions for updated configurations.
                TokenValidationParameters tvp     = Options.TokenValidationParameters.Clone();
                IEnumerable <string>      issuers = new[] { _configuration.Issuer };
                tvp.ValidIssuers      = (tvp.ValidIssuers == null ? issuers : tvp.ValidIssuers.Concat(issuers));
                tvp.IssuerSigningKeys = (tvp.IssuerSigningKeys == null ? _configuration.SigningKeys : tvp.IssuerSigningKeys.Concat(_configuration.SigningKeys));

                ClaimsPrincipal principal   = null;
                SecurityToken   parsedToken = null;
                foreach (var validator in Options.SecurityTokenHandlers)
                {
                    if (validator.CanReadToken(token))
                    {
                        principal = validator.ValidateToken(token, tvp, out parsedToken);
                        break;
                    }
                }

                if (principal == null)
                {
                    throw new SecurityTokenException("no validator found");
                }

                ClaimsIdentity claimsIdentity = principal.Identity as ClaimsIdentity;

                // Retrieve our cached redirect uri
                string state = wsFederationMessage.Wctx;
                // WsFed allows for uninitiated logins, state may be missing.
                AuthenticationProperties properties = GetPropertiesFromWctx(state);
                AuthenticationTicket     ticket     = new AuthenticationTicket(claimsIdentity, properties);

                if (Options.UseTokenLifetime)
                {
                    // Override any session persistence to match the token lifetime.
                    DateTime issued = parsedToken.ValidFrom;
                    if (issued != DateTime.MinValue)
                    {
                        ticket.Properties.IssuedUtc = issued.ToUniversalTime();
                    }
                    DateTime expires = parsedToken.ValidTo;
                    if (expires != DateTime.MinValue)
                    {
                        ticket.Properties.ExpiresUtc = expires.ToUniversalTime();
                    }
                    ticket.Properties.AllowRefresh = false;
                }

                var securityTokenValidatedNotification = new SecurityTokenValidatedNotification <WsFederationMessage, WsFederationAuthenticationOptions>(Context, Options)
                {
                    AuthenticationTicket = ticket,
                    ProtocolMessage      = wsFederationMessage,
                };

                await Options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification);

                if (securityTokenValidatedNotification.HandledResponse)
                {
                    return(GetHandledResponseTicket());
                }
                if (securityTokenValidatedNotification.Skipped)
                {
                    return(null);
                }
                // Flow possible changes
                ticket = securityTokenValidatedNotification.AuthenticationTicket;

                return(ticket);
            }
            catch (Exception exception)
            {
                // We can't await inside a catch block, capture and handle outside.
                authFailedEx = ExceptionDispatchInfo.Capture(exception);
            }

            if (authFailedEx != null)
            {
                _logger.WriteError("Exception occurred while processing message: ", authFailedEx.SourceException);

                // Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the notification.
                if (Options.RefreshOnIssuerKeyNotFound && authFailedEx.SourceException.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException)))
                {
                    Options.ConfigurationManager.RequestRefresh();
                }

                var authenticationFailedNotification = new AuthenticationFailedNotification <WsFederationMessage, WsFederationAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = wsFederationMessage,
                    Exception       = authFailedEx.SourceException
                };
                await Options.Notifications.AuthenticationFailed(authenticationFailedNotification);

                if (authenticationFailedNotification.HandledResponse)
                {
                    return(GetHandledResponseTicket());
                }
                if (authenticationFailedNotification.Skipped)
                {
                    return(null);
                }

                authFailedEx.Throw();
            }

            return(null);
        }
        protected override async Task <AuthenticationTicket> AuthenticateCoreAsync()
        {
            if (Options.CallbackPath.HasValue && Options.CallbackPath != (Request.PathBase + Request.Path))
            {
                return(null);
            }

            OpenIdConnectMessage openIdConnectMessage = null;

            if (string.Equals(Request.Method, "POST", StringComparison.OrdinalIgnoreCase) &&
                !string.IsNullOrWhiteSpace(Request.ContentType) &&
                Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) &&
                Request.Body.CanRead)
            {
                if (!Request.Body.CanSeek)
                {
                    _logger.WriteVerbose("Buffering request body");
                    MemoryStream memoryStream = new MemoryStream();
                    await Request.Body.CopyToAsync(memoryStream);

                    memoryStream.Seek(0, SeekOrigin.Begin);
                    Request.Body = memoryStream;
                }

                IFormCollection form = await Request.ReadFormAsync();

                Request.Body.Seek(0, SeekOrigin.Begin);

                openIdConnectMessage = new OpenIdConnectMessage(form);
            }

            if (openIdConnectMessage == null)
            {
                return(null);
            }

            ExceptionDispatchInfo authFailedEx = null;

            try
            {
                var messageReceivedNotification = new MessageReceivedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = openIdConnectMessage
                };
                await Options.Notifications.MessageReceived(messageReceivedNotification);

                if (messageReceivedNotification.HandledResponse)
                {
                    return(GetHandledResponseTicket());
                }
                if (messageReceivedNotification.Skipped)
                {
                    return(null);
                }

                AuthenticationProperties properties = new AuthenticationProperties();
                properties.RedirectUri = Options.RedirectUri;
                if (properties == null)
                {
                    _logger.WriteWarning("The state field is missing or invalid.");
                    return(null);
                }

                string nonce = null;
                if (Options.ProtocolValidator.RequireNonce)
                {
                    nonce = RetrieveNonce(openIdConnectMessage);
                }

                if (!string.IsNullOrWhiteSpace(openIdConnectMessage.Error))
                {
                    throw new OpenIdConnectProtocolException(
                              string.Format(CultureInfo.InvariantCulture,
                                            openIdConnectMessage.Error,
                                            "", openIdConnectMessage.ErrorDescription ?? string.Empty, openIdConnectMessage.ErrorUri ?? string.Empty));
                }

                if (string.IsNullOrWhiteSpace(openIdConnectMessage.IdToken))
                {
                    _logger.WriteWarning("The id_token is missing.");
                    return(null);
                }

                var securityTokenReceivedNotification = new SecurityTokenReceivedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = openIdConnectMessage,
                };
                await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification);

                if (securityTokenReceivedNotification.HandledResponse)
                {
                    return(GetHandledResponseTicket());
                }
                if (securityTokenReceivedNotification.Skipped)
                {
                    return(null);
                }

                B2CConfigurationManager mgr = Options.ConfigurationManager as B2CConfigurationManager;
                _configuration = await mgr.GetConfigurationAsync(Context.Request.CallCancelled, "b2c_1_sign_in_v2");

                TokenValidationParameters tvp     = Options.TokenValidationParameters.Clone();
                IEnumerable <string>      issuers = new[] { _configuration.Issuer };
                tvp.ValidIssuers        = (tvp.ValidIssuers == null ? issuers : tvp.ValidIssuers.Concat(issuers));
                tvp.IssuerSigningTokens = (tvp.IssuerSigningTokens == null ? _configuration.SigningTokens : tvp.IssuerSigningTokens.Concat(_configuration.SigningTokens));

                SecurityToken   validatedToken;
                ClaimsPrincipal principal      = Options.SecurityTokenHandlers.ValidateToken(openIdConnectMessage.IdToken, tvp, out validatedToken);
                ClaimsIdentity  claimsIdentity = principal.Identity as ClaimsIdentity;

                JwtSecurityToken     jwt    = validatedToken as JwtSecurityToken;
                AuthenticationTicket ticket = new AuthenticationTicket(claimsIdentity, properties);

                if (!string.IsNullOrWhiteSpace(openIdConnectMessage.SessionState))
                {
                    ticket.Properties.Dictionary[OpenIdConnectSessionProperties.SessionState] = openIdConnectMessage.SessionState;
                }

                if (!string.IsNullOrWhiteSpace(_configuration.CheckSessionIframe))
                {
                    ticket.Properties.Dictionary[OpenIdConnectSessionProperties.CheckSessionIFrame] = _configuration.CheckSessionIframe;
                }

                if (Options.UseTokenLifetime)
                {
                    DateTime issued = jwt.ValidFrom;
                    if (issued != DateTime.MinValue)
                    {
                        ticket.Properties.IssuedUtc = issued.ToUniversalTime();
                    }
                    DateTime expires = jwt.ValidTo;
                    if (expires != DateTime.MinValue)
                    {
                        ticket.Properties.ExpiresUtc = expires.ToUniversalTime();
                    }
                    ticket.Properties.AllowRefresh = false;
                }

                var securityTokenValidatedNotification = new SecurityTokenValidatedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options)
                {
                    AuthenticationTicket = ticket,
                    ProtocolMessage      = openIdConnectMessage,
                };
                await Options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification);

                if (securityTokenValidatedNotification.HandledResponse)
                {
                    return(GetHandledResponseTicket());
                }
                if (securityTokenValidatedNotification.Skipped)
                {
                    return(null);
                }
                ticket = securityTokenValidatedNotification.AuthenticationTicket;

                var protocolValidationContext = new OpenIdConnectProtocolValidationContext
                {
                    AuthorizationCode = openIdConnectMessage.Code,
                    Nonce             = nonce,
                };

                Options.ProtocolValidator.Validate(jwt, protocolValidationContext);
                if (openIdConnectMessage.Code != null)
                {
                    var authorizationCodeReceivedNotification = new AuthorizationCodeReceivedNotification(Context, Options)
                    {
                        AuthenticationTicket = ticket,
                        Code             = openIdConnectMessage.Code,
                        JwtSecurityToken = jwt,
                        ProtocolMessage  = openIdConnectMessage,
                        RedirectUri      = ticket.Properties.Dictionary.ContainsKey(OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey) ?
                                           ticket.Properties.Dictionary[OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey] : string.Empty,
                    };
                    await Options.Notifications.AuthorizationCodeReceived(authorizationCodeReceivedNotification);

                    if (authorizationCodeReceivedNotification.HandledResponse)
                    {
                        return(GetHandledResponseTicket());
                    }
                    if (authorizationCodeReceivedNotification.Skipped)
                    {
                        return(null);
                    }
                    ticket = authorizationCodeReceivedNotification.AuthenticationTicket;
                }

                return(ticket);
            }
            catch (Exception exception)
            {
                authFailedEx = ExceptionDispatchInfo.Capture(exception);
            }

            if (authFailedEx != null)
            {
                _logger.WriteError("Exception occurred while processing message: '" + authFailedEx.ToString());

                if (Options.RefreshOnIssuerKeyNotFound && authFailedEx.SourceException.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException)))
                {
                    B2CConfigurationManager mgr = Options.ConfigurationManager as B2CConfigurationManager;
                    mgr.RequestRefresh("b2c_1_sign_in");
                }

                var authenticationFailedNotification = new AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = openIdConnectMessage,
                    Exception       = authFailedEx.SourceException
                };
                await Options.Notifications.AuthenticationFailed(authenticationFailedNotification);

                if (authenticationFailedNotification.HandledResponse)
                {
                    return(GetHandledResponseTicket());
                }
                if (authenticationFailedNotification.Skipped)
                {
                    return(null);
                }

                authFailedEx.Throw();
            }

            return(null);
        }
예제 #10
0
 // Used for avoiding yellow-screen-of-death
 private Task AuthenticationFailed(AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
 {
     notification.HandleResponse();
     notification.Response.Redirect("/Home/Error?message=" + notification.Exception.Message);
     return(Task.FromResult(0));
 }
예제 #11
0
 private Task OnAuthenticationFailed(AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
 {
     notification.HandleResponse();
     notification.Response.Redirect("/Error/ShowError?signIn=true&errorMessage=" + notification.Exception.Message);
     return(Task.FromResult(0));
 }
        /// <summary>
        /// Invoked to process incoming authentication messages.
        /// </summary>
        /// <returns>An <see cref="AuthenticationTicket"/> if successful.</returns>
        protected override async Task <AuthenticationTicket> AuthenticateCoreAsync()
        {
            // Allow login to be constrained to a specific path. Need to make this runtime configurable.
            if (Options.CallbackPath.HasValue && Options.CallbackPath != (Request.PathBase + Request.Path))
            {
                return(null);
            }

            OpenIdConnectMessage openIdConnectMessage = null;

            // assumption: if the ContentType is "application/x-www-form-urlencoded" it should be safe to read as it is small.
            if (string.Equals(Request.Method, "POST", StringComparison.OrdinalIgnoreCase) &&
                !string.IsNullOrWhiteSpace(Request.ContentType)
                // May have media/type; charset=utf-8, allow partial match.
                && Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) &&
                Request.Body.CanRead)
            {
                if (!Request.Body.CanSeek)
                {
                    _logger.WriteVerbose("Buffering request body");
                    // Buffer in case this body was not meant for us.
                    MemoryStream memoryStream = new MemoryStream();
                    await Request.Body.CopyToAsync(memoryStream);

                    memoryStream.Seek(0, SeekOrigin.Begin);
                    Request.Body = memoryStream;
                }

                IFormCollection form = await Request.ReadFormAsync();

                Request.Body.Seek(0, SeekOrigin.Begin);

                // TODO: a delegate on OpenIdConnectAuthenticationOptions would allow for users to hook their own custom message.
                openIdConnectMessage = new OpenIdConnectMessage(form);
            }

            if (openIdConnectMessage == null)
            {
                return(null);
            }

            ExceptionDispatchInfo authFailedEx = null;

            try
            {
                var messageReceivedNotification = new MessageReceivedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = openIdConnectMessage
                };
                await Options.Notifications.MessageReceived(messageReceivedNotification);

                if (messageReceivedNotification.HandledResponse)
                {
                    return(GetHandledResponseTicket());
                }
                if (messageReceivedNotification.Skipped)
                {
                    return(null);
                }

                // runtime always adds state, if we don't find it OR we failed to 'unprotect' it this is not a message we
                // should process.
                AuthenticationProperties properties = GetPropertiesFromState(openIdConnectMessage.State);
                if (properties == null)
                {
                    _logger.WriteWarning("The state field is missing or invalid.");
                    return(null);
                }

                // devs will need to hook AuthenticationFailedNotification to avoid having 'raw' runtime errors displayed to users.
                if (!string.IsNullOrWhiteSpace(openIdConnectMessage.Error))
                {
                    throw new OpenIdConnectProtocolException(
                              string.Format(CultureInfo.InvariantCulture,
                                            Resources.Exception_OpenIdConnectMessageError,
                                            openIdConnectMessage.Error, openIdConnectMessage.ErrorDescription ?? string.Empty, openIdConnectMessage.ErrorUri ?? string.Empty));
                }

                // code is only accepted with id_token, in this version, hence check for code is inside this if
                // OpenIdConnect protocol allows a Code to be received without the id_token
                if (string.IsNullOrWhiteSpace(openIdConnectMessage.IdToken))
                {
                    _logger.WriteWarning("The id_token is missing.");
                    return(null);
                }

                var securityTokenReceivedNotification = new SecurityTokenReceivedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = openIdConnectMessage,
                };
                await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification);

                if (securityTokenReceivedNotification.HandledResponse)
                {
                    return(GetHandledResponseTicket());
                }
                if (securityTokenReceivedNotification.Skipped)
                {
                    return(null);
                }

                if (_configuration == null)
                {
                    _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.Request.CallCancelled);
                }

                // Copy and augment to avoid cross request race conditions for updated configurations.
                TokenValidationParameters tvp     = Options.TokenValidationParameters.Clone();
                IEnumerable <string>      issuers = new[] { _configuration.Issuer };
                tvp.ValidIssuers      = (tvp.ValidIssuers == null ? issuers : tvp.ValidIssuers.Concat(issuers));
                tvp.IssuerSigningKeys = (tvp.IssuerSigningKeys == null ? _configuration.SigningKeys : tvp.IssuerSigningKeys.Concat <SecurityKey>(_configuration.SigningKeys));

                SecurityToken   validatedToken;
                ClaimsPrincipal principal      = Options.SecurityTokenValidator.ValidateToken(openIdConnectMessage.IdToken, tvp, out validatedToken);
                ClaimsIdentity  claimsIdentity = principal.Identity as ClaimsIdentity;

                // claims principal could have changed claim values, use bits received on wire for validation.
                JwtSecurityToken     jwt    = validatedToken as JwtSecurityToken;
                AuthenticationTicket ticket = new AuthenticationTicket(claimsIdentity, properties);

                string nonce = null;
                if (Options.ProtocolValidator.RequireNonce)
                {
                    if (String.IsNullOrWhiteSpace(openIdConnectMessage.Nonce))
                    {
                        openIdConnectMessage.Nonce = jwt.Payload.Nonce;
                    }

                    // deletes the nonce cookie
                    nonce = RetrieveNonce(openIdConnectMessage);
                }

                // remember 'session_state' and 'check_session_iframe'
                if (!string.IsNullOrWhiteSpace(openIdConnectMessage.SessionState))
                {
                    ticket.Properties.Dictionary[OpenIdConnectSessionProperties.SessionState] = openIdConnectMessage.SessionState;
                }

                if (!string.IsNullOrWhiteSpace(_configuration.CheckSessionIframe))
                {
                    ticket.Properties.Dictionary[OpenIdConnectSessionProperties.CheckSessionIFrame] = _configuration.CheckSessionIframe;
                }

                if (Options.UseTokenLifetime)
                {
                    // Override any session persistence to match the token lifetime.
                    DateTime issued = jwt.ValidFrom;
                    if (issued != DateTime.MinValue)
                    {
                        ticket.Properties.IssuedUtc = issued.ToUniversalTime();
                    }
                    DateTime expires = jwt.ValidTo;
                    if (expires != DateTime.MinValue)
                    {
                        ticket.Properties.ExpiresUtc = expires.ToUniversalTime();
                    }
                    ticket.Properties.AllowRefresh = false;
                }

                var securityTokenValidatedNotification = new SecurityTokenValidatedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options)
                {
                    AuthenticationTicket = ticket,
                    ProtocolMessage      = openIdConnectMessage,
                };
                await Options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification);

                if (securityTokenValidatedNotification.HandledResponse)
                {
                    return(GetHandledResponseTicket());
                }
                if (securityTokenValidatedNotification.Skipped)
                {
                    return(null);
                }
                // Flow possible changes
                ticket = securityTokenValidatedNotification.AuthenticationTicket;

                Options.ProtocolValidator.ValidateAuthenticationResponse(new OpenIdConnectProtocolValidationContext()
                {
                    ClientId         = Options.ClientId,
                    ProtocolMessage  = openIdConnectMessage,
                    ValidatedIdToken = jwt,
                    Nonce            = nonce
                });

                if (openIdConnectMessage.Code != null)
                {
                    var authorizationCodeReceivedNotification = new AuthorizationCodeReceivedNotification(Context, Options)
                    {
                        AuthenticationTicket = ticket,
                        Code             = openIdConnectMessage.Code,
                        JwtSecurityToken = jwt,
                        ProtocolMessage  = openIdConnectMessage,
                        RedirectUri      = ticket.Properties.Dictionary.ContainsKey(OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey) ?
                                           ticket.Properties.Dictionary[OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey] : string.Empty,
                    };
                    await Options.Notifications.AuthorizationCodeReceived(authorizationCodeReceivedNotification);

                    if (authorizationCodeReceivedNotification.HandledResponse)
                    {
                        return(GetHandledResponseTicket());
                    }
                    if (authorizationCodeReceivedNotification.Skipped)
                    {
                        return(null);
                    }
                    // Flow possible changes
                    ticket = authorizationCodeReceivedNotification.AuthenticationTicket;
                }

                return(ticket);
            }
            catch (Exception exception)
            {
                // We can't await inside a catch block, capture and handle outside.
                authFailedEx = ExceptionDispatchInfo.Capture(exception);
            }

            if (authFailedEx != null)
            {
                _logger.WriteError("Exception occurred while processing message: ", authFailedEx.SourceException);

                // Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the notification.
                if (Options.RefreshOnIssuerKeyNotFound && authFailedEx.SourceException.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException)))
                {
                    Options.ConfigurationManager.RequestRefresh();
                }

                var authenticationFailedNotification = new AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = openIdConnectMessage,
                    Exception       = authFailedEx.SourceException
                };
                await Options.Notifications.AuthenticationFailed(authenticationFailedNotification);

                if (authenticationFailedNotification.HandledResponse)
                {
                    return(GetHandledResponseTicket());
                }
                if (authenticationFailedNotification.Skipped)
                {
                    return(null);
                }

                authFailedEx.Throw();
            }

            return(null);
        }
예제 #13
0
        /// <summary>
        /// Searches the 'Authorization' header for a 'Bearer' token. If the 'Bearer' token is found, it is validated using <see cref="TokenValidationParameters"/> set in the options.
        /// </summary>
        /// <returns></returns>
        protected override async Task <AuthenticationTicket> AuthenticateCoreAsync()
        {
            string token = null;

            try
            {
                // Give application opportunity to find from a different location, adjust, or reject token
                var messageReceivedNotification =
                    new MessageReceivedNotification <HttpContext, OAuthBearerAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = Context,
                };

                // notification can set the token
                await Options.Notifications.MessageReceived(messageReceivedNotification);

                if (messageReceivedNotification.HandledResponse)
                {
                    return(messageReceivedNotification.AuthenticationTicket);
                }

                if (messageReceivedNotification.Skipped)
                {
                    return(null);
                }

                // If application retrieved token from somewhere else, use that.
                token = messageReceivedNotification.Token;

                if (string.IsNullOrEmpty(token))
                {
                    string authorization = Request.Headers.Get("Authorization");

                    // If no authorization header found, nothing to process further
                    if (string.IsNullOrEmpty(authorization))
                    {
                        return(null);
                    }

                    if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
                    {
                        token = authorization.Substring("Bearer ".Length).Trim();
                    }

                    // If no token found, no further work possible
                    if (string.IsNullOrEmpty(token))
                    {
                        return(null);
                    }
                }

                // notify user token was received
                var securityTokenReceivedNotification =
                    new SecurityTokenReceivedNotification <HttpContext, OAuthBearerAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = Context,
                    SecurityToken   = token,
                };

                await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification);

                if (securityTokenReceivedNotification.HandledResponse)
                {
                    return(securityTokenReceivedNotification.AuthenticationTicket);
                }

                if (securityTokenReceivedNotification.Skipped)
                {
                    return(null);
                }

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

                var validationParameters = Options.TokenValidationParameters.Clone();
                if (_configuration != null)
                {
                    if (validationParameters.ValidIssuer == null && !string.IsNullOrWhiteSpace(_configuration.Issuer))
                    {
                        validationParameters.ValidIssuer = _configuration.Issuer;
                    }
                    else
                    {
                        IEnumerable <string> issuers = new[] { _configuration.Issuer };
                        validationParameters.ValidIssuers = (validationParameters.ValidIssuers == null ? issuers : validationParameters.ValidIssuers.Concat(issuers));
                    }

                    validationParameters.IssuerSigningKeys = (validationParameters.IssuerSigningKeys == null ? _configuration.SigningKeys : validationParameters.IssuerSigningKeys.Concat(_configuration.SigningKeys));
                }

                SecurityToken validatedToken;
                foreach (var validator in Options.SecurityTokenValidators)
                {
                    if (validator.CanReadToken(token))
                    {
                        ClaimsPrincipal      principal         = validator.ValidateToken(token, validationParameters, out validatedToken);
                        AuthenticationTicket ticket            = new AuthenticationTicket(principal, new AuthenticationProperties(), Options.AuthenticationScheme);
                        var securityTokenValidatedNotification = new SecurityTokenValidatedNotification <HttpContext, OAuthBearerAuthenticationOptions>(Context, Options)
                        {
                            ProtocolMessage      = Context,
                            AuthenticationTicket = ticket
                        };

                        if (securityTokenReceivedNotification.HandledResponse)
                        {
                            return(securityTokenValidatedNotification.AuthenticationTicket);
                        }

                        if (securityTokenReceivedNotification.Skipped)
                        {
                            return(null);
                        }

                        return(ticket);
                    }
                }

                throw new InvalidOperationException("No SecurityTokenValidator available for token: " + token ?? "null");
            }
            catch (Exception ex)
            {
                _logger.LogError("Exception occurred while processing message", ex);

                // Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the notification.
                if (Options.RefreshOnIssuerKeyNotFound && ex.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException)))
                {
                    Options.ConfigurationManager.RequestRefresh();
                }

                var authenticationFailedNotification =
                    new AuthenticationFailedNotification <HttpContext, OAuthBearerAuthenticationOptions>(Context, Options)
                {
                    ProtocolMessage = Context,
                    Exception       = ex
                };

                await Options.Notifications.AuthenticationFailed(authenticationFailedNotification);

                if (authenticationFailedNotification.HandledResponse)
                {
                    return(authenticationFailedNotification.AuthenticationTicket);
                }

                if (authenticationFailedNotification.Skipped)
                {
                    return(null);
                }

                throw;
            }
        }
예제 #14
0
 private Task OnAuthenticationFailed(AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> arg)
 {
     arg.HandleResponse();
     arg.Response.Redirect("/?errormessage" + arg.Exception.Message);
     return(Task.FromResult(0));
 }
예제 #15
0
        /// <summary>
        /// Invokes the login procedure (2nd leg of SP-Initiated login). Analagous to Saml20SignonHandler from ASP.Net DLL
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task <AuthenticationTicket> Invoke(IOwinContext context)
        {
            Logger.Debug(TraceMessages.SignOnHandlerCalled);
            ExceptionDispatchInfo authFailedEx = null;

            try {
                var messageReceivedNotification = new MessageReceivedNotification <SamlMessage, SamlAuthenticationOptions>(context, options)
                {
                    ProtocolMessage = new SamlMessage(context, configuration, null)
                };
                await options.Notifications.MessageReceived(messageReceivedNotification);

                if (messageReceivedNotification.HandledResponse)
                {
                    return(null); // GetHandledResponseTicket()
                }
                if (messageReceivedNotification.Skipped)
                {
                    return(null);
                }
                var requestParams = await HandleResponse(context);

                var assertion = context.Get <Saml20Assertion>("Saml2:assertion");
                var securityTokenReceivedNotification = new SecurityTokenReceivedNotification <SamlMessage, SamlAuthenticationOptions>(context, options)
                {
                    ProtocolMessage = new SamlMessage(context, configuration, assertion)
                };
                await options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification);

                if (securityTokenReceivedNotification.HandledResponse)
                {
                    return(null); // GetHandledResponseTicket();
                }
                if (securityTokenReceivedNotification.Skipped)
                {
                    return(null);
                }

                var ticket = await GetAuthenticationTicket(context, requestParams);

                var securityTokenValidatedNotification = new SecurityTokenValidatedNotification <SamlMessage, SamlAuthenticationOptions>(context, options)
                {
                    AuthenticationTicket = ticket,
                    ProtocolMessage      = new SamlMessage(context, configuration, assertion)
                };

                await options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification);

                if (securityTokenValidatedNotification.HandledResponse)
                {
                    return(null); // GetHandledResponseTicket();
                }
                if (securityTokenValidatedNotification.Skipped)
                {
                    return(null); // null;
                }
                // Flow possible changes
                ticket = securityTokenValidatedNotification.AuthenticationTicket;

                context.Authentication.AuthenticationResponseGrant = new AuthenticationResponseGrant(ticket.Identity, ticket.Properties);
                return(ticket);
            }
            catch (Exception ex) {
                authFailedEx = ExceptionDispatchInfo.Capture(ex);
            }
            if (authFailedEx != null)
            {
                Logger.Error("Exception occurred while processing message: " + authFailedEx.SourceException);
                var message = new SamlMessage(context, configuration, context.Get <Saml20Assertion>("Saml2:assertion"));
                var authenticationFailedNotification = new AuthenticationFailedNotification <SamlMessage, SamlAuthenticationOptions>(context, options)
                {
                    ProtocolMessage = message,
                    Exception       = authFailedEx.SourceException
                };
                await options.Notifications.AuthenticationFailed(authenticationFailedNotification);

                if (authenticationFailedNotification.HandledResponse)
                {
                    return(null);//GetHandledResponseTicket();
                }
                if (authenticationFailedNotification.Skipped)
                {
                    return(null); //null
                }

                authFailedEx.Throw();
            }
            return(null);
        }
예제 #16
0
파일: Startup.cs 프로젝트: MartinWa/svvtest
 private static Task AuthenticationFailed(AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> authenticationFailedNotification)
 {
     //       serilogAdapter.Exception(authenticationFailedNotification.Exception);
     return(Task.FromResult(0));
 }