コード例 #1
0
        public async Task <IActionResult> Index()
        {
            // GET + no parameters = metadata request
            if (!Request.QueryString.HasValue)
            {
                _logger.LogDebug("Start WS-Federation metadata request");

                var entity = await _metadata.GenerateAsync(Url.Action("Index", "WsFederation", null, Request.Scheme, Request.Host.Value));

                return(new MetadataResult(entity));
            }

            var url = Url.Action("Index", "WsFederation", null, Request.Scheme, Request.Host.Value) + Request.QueryString;

            _logger.LogDebug("Start WS-Federation request: {url}", url);

            // user can be null here (this differs from HttpContext.User where the anonymous user is filled in)
            var user = await _userSession.GetUserAsync();

            WsFederationMessage message = WsFederationMessage.FromUri(new Uri(url));
            var isSignin = message.IsSignInMessage;

            if (isSignin)
            {
                return(await ProcessSignInAsync(message, user));
            }
            var isSignout = message.IsSignOutMessage;

            if (isSignout)
            {
                return(await ProcessSignOutAsync(message));
            }

            return(BadRequest("Invalid WS-Federation request"));
        }
コード例 #2
0
        /// <summary>
        /// Handles wsignoutcleanup1.0 messages sent to the RemoteSignOutPath
        /// </summary>
        /// <returns></returns>
        protected virtual async Task <bool> HandleRemoteSignOutAsync()
        {
            var message = new WsFederationMessage(Request.Query.Select(pair => new KeyValuePair <string, string[]>(pair.Key, pair.Value)));
            var remoteSignOutContext = new RemoteSignOutContext(Context, Scheme, Options, message);
            await Events.RemoteSignOut(remoteSignOutContext);

            if (remoteSignOutContext.Result != null)
            {
                if (remoteSignOutContext.Result.Handled)
                {
                    Logger.RemoteSignOutHandledResponse();
                    return(true);
                }
                if (remoteSignOutContext.Result.Skipped)
                {
                    Logger.RemoteSignOutSkipped();
                    return(false);
                }
            }

            Logger.RemoteSignOut();

            await Context.SignOutAsync(Options.SignOutScheme);

            return(true);
        }
コード例 #3
0
        public void ConstructorTest(WsFederationMessageTheoryData theoryData)
        {
            TestUtilities.WriteHeader($"{this}.ConstructorTest", theoryData);
            try
            {
                // check default constructor
                var wsFederationMessage1 = new WsFederationMessage
                {
                    IssuerAddress = theoryData.IssuerAddress,
                    Wreply        = theoryData.Wreply,
                    Wct           = theoryData.Wct
                };

                Assert.Equal(theoryData.IssuerAddress, wsFederationMessage1.IssuerAddress);
                Assert.Equal(theoryData.Wreply, wsFederationMessage1.Wreply);
                Assert.Equal(theoryData.Wct, wsFederationMessage1.Wct);

                // check copy constructor
                WsFederationMessage wsFederationMessage2 = new WsFederationMessage(wsFederationMessage1);

                Assert.Equal(theoryData.IssuerAddress, wsFederationMessage2.IssuerAddress);
                Assert.Equal(theoryData.Wreply, wsFederationMessage2.Wreply);
                Assert.Equal(theoryData.Wct, wsFederationMessage2.Wct);

                theoryData.ExpectedException.ProcessNoException();
            }
            catch (Exception ex)
            {
                theoryData.ExpectedException.ProcessException(ex);
            }
        }
コード例 #4
0
        public void Publics()
        {
            string issuerAdderss = @"http://www.gotjwt.com";
            string wreply        = @"http://www.relyingparty.com";
            string wct           = Guid.NewGuid().ToString();
            WsFederationMessage wsFederationMessage = new WsFederationMessage
            {
                IssuerAddress = issuerAdderss,
                Wreply        = wreply,
                Wct           = wct,
            };

            wsFederationMessage.SetParameter("bob", null);
            wsFederationMessage.Parameters.Add("bob", null);
            string uriString = wsFederationMessage.BuildRedirectUrl();
            Uri    uri       = new Uri(uriString);

            WsFederationMessage wsFederationMessageReturned = WsFederationMessage.FromQueryString(uri.Query);

            wsFederationMessageReturned.IssuerAddress = issuerAdderss;
            wsFederationMessageReturned.Parameters.Add("bob", null);
            Assert.IsTrue(MessageComparer.AreEqual(wsFederationMessage, wsFederationMessageReturned));

            wsFederationMessageReturned = WsFederationMessage.FromUri(uri);
            wsFederationMessageReturned.IssuerAddress = issuerAdderss;
            wsFederationMessageReturned.Parameters.Add("bob", null);
            Assert.IsTrue(MessageComparer.AreEqual(wsFederationMessage, wsFederationMessageReturned));
        }
コード例 #5
0
        public void WaSignIn(WsFederationMessageTheoryData theoryData)
        {
            var context = TestUtilities.WriteHeader($"{this}.WaSignIn", theoryData);

            try
            {
                var fedMessage = WsFederationMessage.FromQueryString(theoryData.QueryString);
                var token      = fedMessage.GetToken();
                if (theoryData.TokenValidationParameters != null)
                {
                    theoryData.SecurityTokenHandler.ValidateToken(token, theoryData.TokenValidationParameters, out SecurityToken validatedToken);
                    if (theoryData.SecurityToken != null)
                    {
                        IdentityComparer.AreEqual(theoryData.SecurityToken, validatedToken, context);
                    }
                }
                theoryData.ExpectedException.ProcessNoException(context);
            }
            catch (Exception ex)
            {
                theoryData.ExpectedException.ProcessException(ex, context);
            }

            TestUtilities.AssertFailIfErrors(context);
        }
コード例 #6
0
    /// <summary>
    /// Handles wsignoutcleanup1.0 messages sent to the RemoteSignOutPath
    /// </summary>
    /// <returns></returns>
    protected virtual async Task <bool> HandleRemoteSignOutAsync()
    {
        // ToArray handles the StringValues.IsNullOrEmpty case. We assume non-empty Value does not contain null elements.
#pragma warning disable CS8620 // Argument cannot be used for parameter due to differences in the nullability of reference types.
        var message = new WsFederationMessage(Request.Query.Select(pair => new KeyValuePair <string, string[]>(pair.Key, pair.Value.ToArray())));
#pragma warning restore CS8620 // Argument cannot be used for parameter due to differences in the nullability of reference types.

        var remoteSignOutContext = new RemoteSignOutContext(Context, Scheme, Options, message);
        await Events.RemoteSignOut(remoteSignOutContext);

        if (remoteSignOutContext.Result != null)
        {
            if (remoteSignOutContext.Result.Handled)
            {
                Logger.RemoteSignOutHandledResponse();
                return(true);
            }
            if (remoteSignOutContext.Result.Skipped)
            {
                Logger.RemoteSignOutSkipped();
                return(false);
            }
        }

        Logger.RemoteSignOut();

        await Context.SignOutAsync(Options.SignOutScheme);

        return(true);
    }
コード例 #7
0
        private static WsFederationMessage CreateResponse(SignInValidationResult validationResult, SecurityToken token)
        {
            var handler = CreateTokenHandler(validationResult.RelyingParty.TokenType);
            var client  = validationResult.Client;
            var message = validationResult.WsFederationMessage;
            var rstr    = new RequestSecurityTokenResponse
            {
                CreatedAt = token.ValidFrom,
                ExpiresAt = token.ValidTo,
                AppliesTo = client.ClientId,
                Context   = message.Wctx,
                ReplyTo   = validationResult.ReplyUrl,
                RequestedSecurityToken = token,
                SecurityTokenHandler   = handler,
            };
            var responseMessage = new WsFederationMessage
            {
                IssuerAddress = message.Wreply ?? client.RedirectUris.First(),
                Wa            = WsFederationConstants.WsFederationActions.SignIn,
                Wresult       = rstr.Serialize(),
                Wctx          = message.Wctx
            };

            return(responseMessage);
        }
コード例 #8
0
        public void GetTokenParsingString(WsFederationMessageTheoryData theoryData)
        {
            var context = TestUtilities.WriteHeader($"{this}.GetTokenParsingString", theoryData);

            try
            {
                var token = WsFederationMessage.GetToken(theoryData.Wresult);
                if (token == null && theoryData.Token != null)
                {
                    context.AddDiff("(token == null && theoryData.Token != null)");
                }
                else if (token != null && theoryData.Token == null)
                {
                    context.AddDiff("(token != null && theoryData.Token == null)");
                }
                else if (string.Compare(token, theoryData.Token) != 0)
                {
                    context.AddDiff("string.Compare(token, token2) != 0");
                }

                theoryData.ExpectedException.ProcessNoException(context);
            }
            catch (Exception ex)
            {
                theoryData.ExpectedException.ProcessException(ex, context);
            }

            TestUtilities.AssertFailIfErrors(context);
        }
コード例 #9
0
        public void GetTokenTest(WsFederationMessageTheoryData theoryData)
        {
            var context = TestUtilities.WriteHeader($"{this}.GetTokenTest", theoryData);

            try
            {
                // GetToken (for other than NETSTANDARD 1.4) uses XmlReaders to obtain token from Wresult.
                // GetToken(string) {internal} uses string manipulation to obtain token.
                // The result should be the same token.
                var tokenUsingReader = theoryData.WsFederationMessageTestSet.WsFederationMessage.GetToken();
                var tokenFromString  = WsFederationMessage.GetToken(theoryData.WsFederationMessageTestSet.WsFederationMessage.Wresult);
                if (string.Compare(tokenUsingReader, tokenFromString) != 0)
                {
                    context.AddDiff("string.Compare(tokenUsingReader, tokenFromString) != 0");
                }

                if (theoryData.TokenValidationParameters != null)
                {
                    var tokenHandler = new Saml2SecurityTokenHandler();
                    tokenHandler.ValidateToken(tokenUsingReader, theoryData.TokenValidationParameters, out SecurityToken validatedToken);
                }
                theoryData.ExpectedException.ProcessNoException(context);
            }
            catch (Exception ex)
            {
                theoryData.ExpectedException.ProcessException(ex, context);
            }

            TestUtilities.AssertFailIfErrors(context);
        }
コード例 #10
0
        /// <summary>
        /// Handles Challenge
        /// </summary>
        /// <returns></returns>
        protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
        {
            if (_configuration == null)
            {
                _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted);
            }

            // Save the original challenge URI so we can redirect back to it when we're done.
            if (string.IsNullOrEmpty(properties.RedirectUri))
            {
                properties.RedirectUri = OriginalPathBase + OriginalPath + Request.QueryString;
            }

            var wsFederationMessage = new WsFederationMessage()
            {
                IssuerAddress = _configuration.TokenEndpoint ?? string.Empty,
                Wtrealm       = Options.Wtrealm,
                Wa            = WsFederationConstants.WsFederationActions.SignIn,
            };

            if (!string.IsNullOrEmpty(Options.Wreply))
            {
                wsFederationMessage.Wreply = Options.Wreply;
            }
            else
            {
                wsFederationMessage.Wreply = BuildRedirectUri(Options.CallbackPath);
            }

            GenerateCorrelationId(properties);

            var redirectContext = new RedirectContext(Context, Scheme, Options, properties)
            {
                ProtocolMessage = wsFederationMessage
            };
            await Events.RedirectToIdentityProvider(redirectContext);

            if (redirectContext.Handled)
            {
                return;
            }

            wsFederationMessage = redirectContext.ProtocolMessage;

            if (!string.IsNullOrEmpty(wsFederationMessage.Wctx))
            {
                properties.Items[WsFederationDefaults.UserstatePropertiesKey] = wsFederationMessage.Wctx;
            }

            wsFederationMessage.Wctx = Uri.EscapeDataString(Options.StateDataFormat.Protect(properties));

            var redirectUri = wsFederationMessage.CreateSignInUrl();

            if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute))
            {
                Logger.MalformedRedirectUri(redirectUri);
            }
            Response.Redirect(redirectUri);
        }
コード例 #11
0
        public async Task <WsFederationSigninValidationResult> ValidateAsync(WsFederationMessage message, ClaimsPrincipal user)
        {
            _logger.LogDebug("Start WsFederation signin request validator.");

            var validatedRequest = new ValidatedWsFederationSigninRequest
            {
                RequestMessage = message,
                Subject        = user
            };

            if (string.IsNullOrEmpty(message.Wa))
            {
                _logger.LogError("Wa is missing from the request.", validatedRequest);
                return(new WsFederationSigninValidationResult(validatedRequest, "Missing wa", "No 'wa' was specified as part of the request."));
            }

            if (message.Wa != WsFederationConstants.WsFederationActions.SignIn)
            {
                _logger.LogWarning("Unsupported action.", validatedRequest);
                return(new WsFederationSigninValidationResult(validatedRequest, "Unsupported action.", $"wa={message.Wa} is not supported."));
            }

            if (string.IsNullOrEmpty(message.Wtrealm))
            {
                _logger.LogError("Wtrealm is missing from the request.", validatedRequest);
                return(new WsFederationSigninValidationResult(validatedRequest, "Missing Wtrealm.", "Wtrealm was not passed in as a parameter."));
            }

            var client = await _clients.FindEnabledClientByIdAsync(message.Wtrealm);

            if (client == null)
            {
                _logger.LogError("There is no client configured that matches the wtrealm parameter of the incoming request.", validatedRequest);
                return(new WsFederationSigninValidationResult(validatedRequest, "No Client.", "There is no client configured that matches the wtrealm parameter of the incoming request."));
            }

            if (string.IsNullOrEmpty(message.Wreply))
            {
                _logger.LogInformation("Wreply is missing from the request. Using the defualt wreply.", validatedRequest);
                message.Wreply = client.RedirectUris.FirstOrDefault();
            }

            if (!client.RedirectUris.Contains(message.Wreply))
            {
                _logger.LogError("The passed in redirect url is not valid for the given client.", validatedRequest);
                return(new WsFederationSigninValidationResult(validatedRequest, "Invalid redirect uri.", "The passed in redirect url is not valid for the given client."));
            }
            validatedRequest.SetClient(client);

            if (validatedRequest.Client.ProtocolType != IdentityServerConstants.ProtocolTypes.WsFederation)
            {
                _logger.LogError("The client identified by the wtrealm does not support WsFederation.", validatedRequest);
                return(new WsFederationSigninValidationResult(validatedRequest, "Invalid protocol.", "The client identified by the wtrealm does not support WsFederation."));
            }

            _logger.LogTrace("WsFederation signin request validation successful.");
            return(new WsFederationSigninValidationResult(validatedRequest));
        }
コード例 #12
0
ファイル: MessageComparer.cs プロジェクト: zbjlala/netcoreRSA
        public static bool AreEqual(WsFederationMessage wsFederationMessage1, WsFederationMessage wsFederationMessage2)
        {
            if (!MessageComparer.AreEqual(wsFederationMessage1 as AuthenticationProtocolMessage, wsFederationMessage2 as AuthenticationProtocolMessage))
            {
                return(false);
            }

            return(true);
        }
コード例 #13
0
        public void ParametersTest(WsFederationMessageTheoryData theoryData)
        {
            TestUtilities.WriteHeader($"{this}.ParametersTest", theoryData);
            try
            {
                var wsFederationMessage = new WsFederationMessage
                {
                    IssuerAddress = theoryData.IssuerAddress,
                    Wreply        = theoryData.Wreply,
                    Wct           = theoryData.Wct
                };

                Assert.Equal(theoryData.IssuerAddress, wsFederationMessage.IssuerAddress);
                Assert.Equal(theoryData.Wreply, wsFederationMessage.Wreply);
                Assert.Equal(theoryData.Wct, wsFederationMessage.Wct);

                // add parameter
                wsFederationMessage.SetParameter(theoryData.Parameter1.Key, theoryData.Parameter1.Value);

                // add parameters
                var nameValueCollection = new NameValueCollection
                {
                    { theoryData.Parameter2.Key, theoryData.Parameter2.Value },
                    { theoryData.Parameter3.Key, theoryData.Parameter3.Value }
                };
                wsFederationMessage.SetParameters(nameValueCollection);

                // validate the parameters are added
                Assert.Equal(theoryData.Parameter1.Value, wsFederationMessage.Parameters[theoryData.Parameter1.Key]);
                Assert.Equal(theoryData.Parameter2.Value, wsFederationMessage.Parameters[theoryData.Parameter2.Key]);
                Assert.Equal(theoryData.Parameter3.Value, wsFederationMessage.Parameters[theoryData.Parameter3.Key]);

                // remove parameter
                wsFederationMessage.SetParameter(theoryData.Parameter1.Key, null);

                // validate the parameter is removed
                Assert.False(wsFederationMessage.Parameters.ContainsKey(theoryData.Parameter1.Key));

                // create redirectUri
                var uriString = wsFederationMessage.BuildRedirectUrl();
                Uri uri       = new Uri(uriString);

                // convert query back to WsFederationMessage
                var wsFederationMessageReturned = WsFederationMessage.FromQueryString(uri.Query);

                // validate the parameters in the returned wsFederationMessage
                Assert.Equal(theoryData.Parameter2.Value, wsFederationMessageReturned.Parameters[theoryData.Parameter2.Key]);
                Assert.Equal(theoryData.Parameter3.Value, wsFederationMessageReturned.Parameters[theoryData.Parameter3.Key]);

                theoryData.ExpectedException.ProcessNoException();
            }
            catch (Exception ex)
            {
                theoryData.ExpectedException.ProcessException(ex);
            }
        }
コード例 #14
0
        /// <summary>
        /// Handles Signout
        /// </summary>
        /// <returns></returns>
        public virtual async Task SignOutAsync(AuthenticationProperties?properties)
        {
            var target = ResolveTarget(Options.ForwardSignOut);

            if (target != null)
            {
                await Context.SignOutAsync(target, properties);

                return;
            }

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

            var wsFederationMessage = new WsFederationMessage()
            {
                IssuerAddress = _configuration.TokenEndpoint ?? string.Empty,
                Wtrealm       = Options.Wtrealm,
                Wa            = WsFederationConstants.WsFederationActions.SignOut,
            };

            // Set Wreply in order:
            // 1. properties.Redirect
            // 2. Options.SignOutWreply
            // 3. Options.Wreply
            if (properties != null && !string.IsNullOrEmpty(properties.RedirectUri))
            {
                wsFederationMessage.Wreply = BuildRedirectUriIfRelative(properties.RedirectUri);
            }
            else if (!string.IsNullOrEmpty(Options.SignOutWreply))
            {
                wsFederationMessage.Wreply = BuildRedirectUriIfRelative(Options.SignOutWreply);
            }
            else if (!string.IsNullOrEmpty(Options.Wreply))
            {
                wsFederationMessage.Wreply = BuildRedirectUriIfRelative(Options.Wreply);
            }

            var redirectContext = new RedirectContext(Context, Scheme, Options, properties)
            {
                ProtocolMessage = wsFederationMessage
            };
            await Events.RedirectToIdentityProvider(redirectContext);

            if (!redirectContext.Handled)
            {
                var redirectUri = redirectContext.ProtocolMessage.CreateSignOutUrl();
                if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute))
                {
                    Logger.MalformedRedirectUri(redirectUri);
                }
                Response.Redirect(redirectUri);
            }
        }
コード例 #15
0
        /// <summary>
        /// Handles Signout
        /// </summary>
        /// <returns></returns>
        protected override async Task ApplyResponseGrantAsync()
        {
            AuthenticationResponseRevoke signout = Helper.LookupSignOut(Options.AuthenticationType, Options.AuthenticationMode);

            if (signout == null)
            {
                return;
            }

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

            WsFederationMessage wsFederationMessage = new WsFederationMessage()
            {
                IssuerAddress = _configuration.TokenEndpoint ?? string.Empty,
                Wtrealm       = Options.Wtrealm,
                Wa            = WsFederationActions.SignOut,
            };

            // Set Wreply in order:
            // 1. properties.Redirect
            // 2. Options.SignOutWreply
            // 3. Options.Wreply
            AuthenticationProperties properties = signout.Properties;

            if (properties != null && !string.IsNullOrEmpty(properties.RedirectUri))
            {
                wsFederationMessage.Wreply = properties.RedirectUri;
            }
            else if (!string.IsNullOrWhiteSpace(Options.SignOutWreply))
            {
                wsFederationMessage.Wreply = Options.SignOutWreply;
            }
            else if (!string.IsNullOrWhiteSpace(Options.Wreply))
            {
                wsFederationMessage.Wreply = Options.Wreply;
            }

            var notification = new RedirectToIdentityProviderNotification <WsFederationMessage, WsFederationAuthenticationOptions>(Context, Options)
            {
                ProtocolMessage = wsFederationMessage
            };
            await Options.Notifications.RedirectToIdentityProvider(notification);

            if (!notification.HandledResponse)
            {
                string redirectUri = notification.ProtocolMessage.CreateSignOutUrl();
                if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute))
                {
                    _logger.WriteWarning("The sign-out redirect URI is malformed: " + redirectUri);
                }
                Response.Redirect(redirectUri);
            }
        }
コード例 #16
0
        public async Task <WsFederationSignoutValidationResult> ValidateAsync(WsFederationMessage message)
        {
            _logger.LogDebug("Start WsFederation signout request validator.");

            var validatedRequest = new ValidatedWsFederationSignoutRequest
            {
                RequestMessage = message
            };

            validatedRequest.SessionId = await _userSession.GetSessionIdAsync();

            validatedRequest.ClientIds = await _userSession.GetClientListAsync();

            IEnumerable <string> postLogoutRedirectUris;

            //Wtrealm is not really part of the standard for signout, but it appears that some implementations include it.
            //If the wtrealm is specified, respect it. Otherwise, search all of the user's known clients for the wreply.
            if (!string.IsNullOrEmpty(message.Wtrealm))
            {
                _logger.LogDebug("Wtrealm was specified. Using PostLogoutRedirectUris for only that client.", validatedRequest);
                var client = await _clients.FindEnabledClientByIdAsync(message.Wtrealm);

                if (client == null)
                {
                    _logger.LogError("There is no client configured that matches the wtrealm parameter of the incoming request.", validatedRequest);
                    return(new WsFederationSignoutValidationResult(validatedRequest, "No Client.", "There is no client configured that matches the wtrealm parameter of the incoming request."));
                }
                postLogoutRedirectUris = client.PostLogoutRedirectUris;
            }
            else
            {
                _logger.LogDebug("Wtrealm was not specified. Using PostLogoutRedirectUris for all clients that the user has authenticated with.", validatedRequest);
                var tasks   = validatedRequest.ClientIds.Select(async c => await _clients.FindEnabledClientByIdAsync(c)).ToList();
                var clients = await Task.WhenAll(tasks);

                postLogoutRedirectUris = clients.SelectMany(c => c.PostLogoutRedirectUris).Where(uri => !string.IsNullOrEmpty(uri));
            }

            //This behavior might be odd. If the user is authenticated with multiple clients, it's probably bad to redirect them to a random client....
            if (string.IsNullOrEmpty(message.Wreply))
            {
                _logger.LogInformation("Wreply is missing from the request. Using the defualt wreply.", validatedRequest);
                validatedRequest.PostLogOutUri = postLogoutRedirectUris.FirstOrDefault();
            }
            else if (postLogoutRedirectUris.Contains(message.Wreply))
            {
                validatedRequest.PostLogOutUri = message.Wreply;
            }
            else
            {
                _logger.LogError("The passed in redirect url is not valid for the given client.", validatedRequest);
                return(new WsFederationSignoutValidationResult(validatedRequest, "Invalid redirect uri.", "The passed in redirect url is not valid for the given client."));
            }
            _logger.LogTrace("WsFederation signout request validation successful.");
            return(new WsFederationSignoutValidationResult(validatedRequest));
        }
コード例 #17
0
        public static bool AreWsFederationMessagesEqual(WsFederationMessage message1, WsFederationMessage message2, CompareContext context)
        {
            var localContext = new CompareContext(context);

            if (ContinueCheckingEquality(message1, message2, localContext))
            {
                CompareAllPublicProperties(message1, message2, localContext);
            }

            return(context.Merge(localContext));
        }
        private WsFederationMessage GetSignInRequestMessage(string returnUrl)
        {
            var uri = new Uri("https://dummy.com" + returnUrl);
            WsFederationMessage message = WsFederationMessage.FromUri(uri);

            if (message.IsSignInMessage)
            {
                return(message);
            }
            return(null);
        }
コード例 #19
0
        private WsFederationMessage GetSignInRequestMessage(string returnUrl)
        {
            var decoded = WebUtility.UrlDecode(returnUrl);
            WsFederationMessage message = WsFederationMessage.FromQueryString(decoded);

            if (message.IsSignInMessage)
            {
                return(message);
            }
            return(null);
        }
コード例 #20
0
        public void WsFederationAuthenticationMessage_GetSets()
        {
            WsFederationMessage wsFederationMessage = new WsFederationMessage();

            Type type = typeof(WsFederationParameterNames);

            FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static);
            foreach (FieldInfo fieldInfo in fields)
            {
                TestUtilities.GetSet(wsFederationMessage, fieldInfo.Name, null, new object[] { fieldInfo.Name, null, fieldInfo.Name + fieldInfo.Name });
            }
        }
コード例 #21
0
ファイル: WsFederationHandler.cs プロジェクト: Tratcher/WsFed
        /// <summary>
        /// Handles Challenge
        /// </summary>
        /// <returns></returns>
        protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
        {
            if (_configuration == null)
            {
                _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted);
            }

            string baseUri =
                Request.Scheme +
                Uri.SchemeDelimiter +
                Request.Host +
                Request.PathBase;

            string currentUri =
                baseUri +
                Request.Path +
                Request.QueryString;

            // Save the original challenge URI so we can redirect back to it when we're done.
            if (string.IsNullOrEmpty(properties.RedirectUri))
            {
                properties.RedirectUri = currentUri;
            }

            WsFederationMessage wsFederationMessage = new WsFederationMessage()
            {
                IssuerAddress = _configuration.TokenEndpoint ?? string.Empty,
                Wtrealm       = Options.Wtrealm,
                Wctx          = WsFederationDefaults.WctxKey + "=" + Uri.EscapeDataString(Options.StateDataFormat.Protect(properties)),
                Wa            = WsFederationConstants.WsFederationActions.SignIn,
            };

            if (!string.IsNullOrWhiteSpace(Options.Wreply))
            {
                wsFederationMessage.Wreply = Options.Wreply;
            }

            var redirectContext = new RedirectContext(Context, Scheme, Options, properties)
            {
                ProtocolMessage = wsFederationMessage
            };
            await Options.Events.RedirectToIdentityProvider(redirectContext);

            if (!redirectContext.Handled)
            {
                string redirectUri = redirectContext.ProtocolMessage.CreateSignInUrl();
                if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute))
                {
                    Logger.LogWarning("The sign-in redirect URI is malformed: " + redirectUri);
                }
                Response.Redirect(redirectUri);
            }
        }
        public async Task WsFederation_signin_request_with_wfresh_user_is_authenticated_wfresh_in_time_frame_return_assertion_success()
        {
            // login user
            var subjectId     = "user1";
            var loginUrl      = string.Format("/account/login?subjectId={0}", WebUtility.UrlEncode(subjectId));
            var loginResponse = await _client.GetAsync(loginUrl);

            var authTime = DateTime.UtcNow;

            // create ws fed sigin message with wfresh=5
            var wsMessage = new WsFederationMessage
            {
                Wa            = "wsignin1.0",
                IssuerAddress = "/wsfederation",
                Wtrealm       = "urn:owinrp",
                Wreply        = "http://localhost:10313/",
                Wfresh        = "5",
            };
            var signInUrl = wsMessage.CreateSignInUrl();
            var request   = new HttpRequestMessage(HttpMethod.Get, signInUrl);

            // test server doesnt save cookies between requests,
            // so we set them explicitly for the next request
            request.SetCookiesFromResponse(loginResponse);

            var response = await _client.SendAsync(request);

            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            var contentAsText = await response.Content.ReadAsStringAsync();

            Assert.NotEqual(String.Empty, contentAsText);
            Assert.Contains("action=\"http://localhost:10313/\"", contentAsText);

            // extract wreturn to use it later to check if our token is a valid token
            var wreturn           = ExtractInBetween(contentAsText, "wresult\" value=\"", "\"");
            var wsResponseMessage = new WsFederationMessage
            {
                Wresult = WebUtility.HtmlDecode(wreturn),
            };
            var tokenString  = wsResponseMessage.GetToken();
            var handler      = new SamlSecurityTokenHandler();
            var canReadToken = handler.CanReadToken(tokenString);

            Assert.True(canReadToken);
            var token          = handler.ReadSamlToken(tokenString);
            var authStatements = token.Assertion.Statements.OfType <SamlAuthenticationStatement>();

            Assert.Equal(1, authStatements.Count());
            var authStatement = authStatements.First();

            Assert.True(authStatement.AuthenticationInstant <= authTime.AddMinutes(5));
        }
コード例 #23
0
        public async Task <IEndpointResult> ProcessAsync(HttpContext context)
        {
            _logger.LogDebug("Processing WsFederation request.");

            if (!HttpMethods.IsGet(context.Request.Method))
            {
                _logger.LogWarning($"WsFederation endpoint only supports GET requests. Current method is {context.Request.Method}");
                return(new StatusCodeResult(HttpStatusCode.MethodNotAllowed));
            }

            var queryString = context.Request.QueryString;

            _logger.LogDebug($"Proccessing WsFederation signin request with QueryString: {queryString}.");

            var message = WsFederationMessage.FromQueryString(queryString.Value);

            var user = await _userSession.GetUserAsync();

            if (message.IsSignOutMessage)
            {
                var signoutValidationResult = await _signoutValidator.ValidateAsync(message);

                return(new WsFederationSignoutResult(signoutValidationResult));
            }
            else //Sign in validator also handles errors for unsupported wa
            {
                var validationResult = await _signinValidator.ValidateAsync(message, user);

                if (validationResult.IsError)
                {
                    _logger.LogError("WsFederation Signin request validation failed.");
                    return(new WsFederationSigninResult(new WsFederationSigninResponse
                    {
                        Request = validationResult.ValidatedRequest,
                        Error = validationResult.Error,
                        ErrorDescription = validationResult.ErrorDescription
                    }));
                }

                //if needed, show login page
                if (IsLoginRequired(user, message))
                {
                    return(new WsFederationLoginPageResult(validationResult.ValidatedRequest));
                }

                //Otherwise, return result
                var response = await _responseGenerator.GenerateResponseAsync(validationResult.ValidatedRequest);

                _logger.LogTrace("End get WsFederation signin request.");
                return(new WsFederationSigninResult(response));
            }
        }
コード例 #24
0
        /// <summary>
        /// Handles Signout
        /// </summary>
        /// <returns></returns>
        protected override async Task ApplyResponseGrantAsync()
        {
            AuthenticationResponseRevoke signout = Helper.LookupSignOut(Options.AuthenticationType, Options.AuthenticationMode);

            if (signout != null)
            {
                object obj = null;
                Context.Environment.TryGetValue("wsfed.SignOutRedirect", out obj);
                string wreply = obj as string;

                WsFederationMessage wsFederationMessage = new WsFederationMessage()
                {
                    IssuerAddress = Options.IssuerAddress ?? string.Empty,
                    Wtrealm       = Options.Wtrealm,
                };

                if (!string.IsNullOrWhiteSpace(wreply))
                {
                    wsFederationMessage.Wreply = wreply;
                }
                else if (!string.IsNullOrWhiteSpace(Options.Wreply))
                {
                    wsFederationMessage.Wreply = Options.Wreply;
                }

                if (Options.Notifications != null && Options.Notifications.RedirectToIdentityProvider != null)
                {
                    RedirectToIdentityProviderNotification <WsFederationMessage> notification =
                        new RedirectToIdentityProviderNotification <WsFederationMessage> {
                        ProtocolMessage = wsFederationMessage
                    };
                    await Options.Notifications.RedirectToIdentityProvider(notification);

                    if (notification.Cancel)
                    {
                        return;
                    }
                }

                string redirect = wsFederationMessage.CreateSignOutQueryString();
                if (!Uri.IsWellFormedUriString(redirect, UriKind.Absolute))
                {
                    _logger.WriteError(string.Format(CultureInfo.InvariantCulture, "The WsFederation sign-out redirect uri is not well formed: '{0}'", redirect));
                    return;
                }

                Response.Redirect(redirect);
            }
        }
コード例 #25
0
        public void CompareWsFederationMessages()
        {
            TestUtilities.WriteHeader($"{this}.CompareWsFederationMessages", true);
            var context  = new CompareContext($"{this}.CompareWsFederationMessages");
            var message1 = new WsFederationMessage {
                Wa = Guid.NewGuid().ToString()
            };
            var message2 = new WsFederationMessage {
                Wa = Guid.NewGuid().ToString()
            };

            IdentityComparer.AreEqual(message1, message2, context);

            Assert.True(context.Diffs.Count(s => s == "Wa:") == 1);
        }
        public async Task WsFederation_signin_request_user_not_authenticated_redirect_to_login_page_success()
        {
            var wsMessage = new WsFederationMessage
            {
                IssuerAddress = "/wsfederation",
                Wtrealm       = "urn:owinrp",
                Wreply        = "http://localhost:10313/",
            };
            var signInUrl = wsMessage.CreateSignInUrl();
            var response  = await _client.GetAsync(signInUrl);

            Assert.Equal(HttpStatusCode.Found, response.StatusCode);
            var expectedLocation = "/Account/Login?ReturnUrl=%2Fwsfederation%3Fwtrealm%3Durn%253Aowinrp%26wreply%3Dhttp%253A%252F%252Flocalhost%253A10313%252F%26wa%3Dwsignin1.0";

            Assert.Equal(expectedLocation, response.Headers.Location.OriginalString);
        }
コード例 #27
0
ファイル: WsFederationHandler.cs プロジェクト: Tratcher/WsFed
        /// <summary>
        /// Handles Signout
        /// </summary>
        /// <returns></returns>
        public async virtual Task SignOutAsync(AuthenticationProperties properties)
        {
            if (_configuration == null)
            {
                _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted);
            }

            var wsFederationMessage = new WsFederationMessage()
            {
                IssuerAddress = _configuration.TokenEndpoint ?? string.Empty,
                Wtrealm       = Options.Wtrealm,
                Wa            = WsFederationConstants.WsFederationActions.SignOut,
            };

            // Set Wreply in order:
            // 1. properties.Redirect
            // 2. Options.SignOutWreply
            // 3. Options.Wreply
            if (properties != null && !string.IsNullOrEmpty(properties.RedirectUri))
            {
                wsFederationMessage.Wreply = properties.RedirectUri;
            }
            else if (!string.IsNullOrWhiteSpace(Options.SignOutWreply))
            {
                wsFederationMessage.Wreply = Options.SignOutWreply;
            }
            else if (!string.IsNullOrWhiteSpace(Options.Wreply))
            {
                wsFederationMessage.Wreply = Options.Wreply;
            }

            var redirectContext = new RedirectContext(Context, Scheme, Options, properties)
            {
                ProtocolMessage = wsFederationMessage
            };
            await Options.Events.RedirectToIdentityProvider(redirectContext);

            if (!redirectContext.Handled)
            {
                string redirectUri = redirectContext.ProtocolMessage.CreateSignOutUrl();
                if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute))
                {
                    Logger.LogWarning("The sign-out redirect URI is malformed: " + redirectUri);
                }
                Response.Redirect(redirectUri);
            }
        }
        public async Task WsFederation_sigin_request_for_logged_in_user_return_assertion_success()
        {
            // login user
            var subjectId     = "user1";
            var loginUrl      = string.Format("/account/login?subjectId={0}", WebUtility.UrlEncode(subjectId));
            var loginResponse = await _client.GetAsync(loginUrl);

            Assert.Equal(HttpStatusCode.OK, loginResponse.StatusCode);

            // create ws fed sign in message
            var wsSignInMessage = new WsFederationMessage
            {
                Wa            = "wsignin1.0",
                IssuerAddress = "/wsfederation",
                Wtrealm       = "urn:owinrp",
                Wreply        = "http://localhost:10313/",
            };
            var signInUrl = wsSignInMessage.CreateSignInUrl();
            var request   = new HttpRequestMessage(HttpMethod.Get, signInUrl);

            // test server doesnt save cookies between requests,
            // so we set them explicitly for the next request
            request.SetCookiesFromResponse(loginResponse);

            // send ws fed sign in request
            var wsResponse = await _client.SendAsync(request);

            Assert.Equal(HttpStatusCode.OK, wsResponse.StatusCode);
            var contentAsText = await wsResponse.Content.ReadAsStringAsync();

            Assert.NotEqual(String.Empty, contentAsText);
            Assert.Contains("action=\"http://localhost:10313/\"", contentAsText);
            // extract wreturn to use it later to check if our token is a valid token
            var wreturn = ExtractInBetween(contentAsText, "wresult\" value=\"", "\"");

            Assert.False(wreturn.StartsWith("%EF%BB%BF")); //don't start with BOM (Byte Order Mark)
            var wsMessage = new WsFederationMessage
            {
                Wresult = WebUtility.HtmlDecode(wreturn),
            };
            var tokenString  = wsMessage.GetToken();
            var handler      = new SamlSecurityTokenHandler();
            var canReadToken = handler.CanReadToken(tokenString);

            Assert.True(canReadToken);
        }
コード例 #29
0
        private async Task <IActionResult> ProcessSignOutAsync(WsFederationMessage message)
        {
            if (string.IsNullOrWhiteSpace(message.Wreply) ||
                string.IsNullOrWhiteSpace(message.Wtrealm))
            {
                return(RedirectToLogOut());
            }

            var result = await _signoutValidator.ValidateAsync(message, User);

            if (result.IsError)
            {
                throw new Exception(result.Error);
            }

            return(await RedirectToLogOutAsync(result));
        }
コード例 #30
0
        public void QueryStringTest(WsFederationMessageTheoryData theoryData)
        {
            var context = TestUtilities.WriteHeader($"{this}.QueryStringTest", theoryData);

            try
            {
                var wsFederationMessage = WsFederationMessage.FromQueryString(theoryData.WsFederationMessageTestSet.Xml);
                theoryData.ExpectedException.ProcessNoException();
                IdentityComparer.AreWsFederationMessagesEqual(wsFederationMessage, theoryData.WsFederationMessageTestSet.WsFederationMessage, context);
            }
            catch (Exception ex)
            {
                theoryData.ExpectedException.ProcessException(ex);
            }

            TestUtilities.AssertFailIfErrors(context);
        }