public async Task WsFederation_login_return_assertion_success() { var loginUrl = "/account/login?returnUrl=%2Fwsfederation%3Fwtrealm%3Durn%253Aowinrp%26wreply%3Dhttp%253A%252F%252Flocalhost%253A10313%252F%26wa%3Dwsignin1.0"; var response = await _client.GetAsync(loginUrl); Assert.Equal(HttpStatusCode.Found, response.StatusCode); var wsEndpointUrl = "/wsfederation?wtrealm=urn%3Aowinrp&wreply=http%3A%2F%2Flocalhost%3A10313%2F&wa=wsignin1.0"; Assert.Equal(wsEndpointUrl, response.Headers.Location.OriginalString); var request = GetRequest(wsEndpointUrl, response); var wsResponse = await _client.SendAsync(request); Assert.Equal(HttpStatusCode.OK, wsResponse.StatusCode); var contentAsText = await wsResponse.Content.ReadAsStringAsync(); Assert.Contains("action=\"http://localhost:10313/\"", contentAsText); 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); }
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); }
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); }
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)); }
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); }
private async Task <SecurityTokenContext> RunSecurityTokenReceivedEventAsync(WsFederationMessage message) { Logger.LogTrace($"SecurityTokenReceived: {message.GetToken()}"); var securityTokenContext = new SecurityTokenContext(Context, Options) { ProtocolMessage = message }; await Options.Events.SecurityTokenReceived(securityTokenContext); if (securityTokenContext.HandledResponse) { Logger.LogDebug("SecurityTokenContext.HandledResponse"); } else if (securityTokenContext.Skipped) { Logger.LogDebug("SecurityTokenContext.HandledResponse"); } return(securityTokenContext); }
public async Task WsFederation_signin_request_with_wfresh_set_to_0_user_is_authenticated_force_resignin_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; Thread.Sleep(3000); // TODO: bad workaround to sumulate login for 3 seconds // create ws fed sigin message with wfresh var wsMessage = new WsFederationMessage { Wa = "wsignin1.0", IssuerAddress = "/wsfederation", Wtrealm = "urn:owinrp", Wreply = "http://localhost:10313/", Wfresh = "0", }; var uri = wsMessage.CreateSignInUrl(); var request = new HttpRequestMessage(HttpMethod.Get, uri); // test server doesnt save cookies between requests, // so we set them explicitly for the next request request.SetCookiesFromResponse(loginResponse); // make auth request, for allready logged in user var response = await _client.SendAsync(request); // redirect to sign in package because we enforce it with wfresh=0 Assert.Equal(HttpStatusCode.Redirect, response.StatusCode); uri = response.Headers.Location.OriginalString + "&subjectId=" + subjectId; request = new HttpRequestMessage(HttpMethod.Get, uri); request.SetCookiesFromResponse(response); // login again to satisfy wfresh=0 response = await _client.SendAsync(request); Assert.Equal(HttpStatusCode.Redirect, response.StatusCode); uri = response.Headers.Location.OriginalString; request = new HttpRequestMessage(HttpMethod.Get, uri); request.SetCookiesFromResponse(response); // do the redirect to auth endpoint 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)); }
protected override async Task <AuthenticationTicket> AuthenticateCoreAsync() { // Allow login to be constrained to a specific path. if (Options.CallbackPath.HasValue && Options.CallbackPath != Request.Path) { return(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) { // 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(); // Post preview release: a delegate on WsFederationAuthenticationOptions would allow for users to hook their own custom message. WsFederationMessage wsFederationMessage = new WsFederationMessage(form); if (!wsFederationMessage.IsSignInMessage) { Request.Body.Seek(0, SeekOrigin.Begin); return(null); } MessageReceivedNotification <WsFederationMessage> messageReceivedNotification = null; if (Options.Notifications != null && Options.Notifications.MessageReceived != null) { messageReceivedNotification = new MessageReceivedNotification <WsFederationMessage> { ProtocolMessage = wsFederationMessage }; await Options.Notifications.MessageReceived(messageReceivedNotification); } if (messageReceivedNotification != null && messageReceivedNotification.Cancel) { return(null); } if (wsFederationMessage.Wresult != null) { string token = wsFederationMessage.GetToken(); if (Options.Notifications != null && Options.Notifications.SecurityTokenReceived != null) { SecurityTokenReceivedNotification securityTokenReceivedNotification = new SecurityTokenReceivedNotification { SecurityToken = token }; await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification); if (securityTokenReceivedNotification.Cancel) { return(null); } } ExceptionDispatchInfo authFailedEx = null; try { ClaimsPrincipal principal = Options.SecurityTokenHandlers.ValidateToken(token, Options.TokenValidationParameters); ClaimsIdentity claimsIdentity = principal.Identity as ClaimsIdentity; // Retrieve our cached redirect uri string state = wsFederationMessage.Wctx; AuthenticationProperties properties = GetPropertiesFromWctx(state); AuthenticationTicket ticket = new AuthenticationTicket(claimsIdentity, properties); Request.Context.Authentication.SignIn(claimsIdentity); if (Options.Notifications != null && Options.Notifications.SecurityTokenValidated != null) { await Options.Notifications.SecurityTokenValidated(new SecurityTokenValidatedNotification { AuthenticationTicket = ticket }); } return(ticket); } catch (Exception exception) { // We can't await inside a catch block, capture and handle outside. authFailedEx = ExceptionDispatchInfo.Capture(exception); } if (authFailedEx != null) { if (Options.Notifications != null && Options.Notifications.AuthenticationFailed != null) { // Post preview release: user can update metadata, need consistent messaging. var authenticationFailedNotification = new AuthenticationFailedNotification <WsFederationMessage>() { ProtocolMessage = wsFederationMessage, Exception = authFailedEx.SourceException }; await Options.Notifications.AuthenticationFailed(authenticationFailedNotification); if (!authenticationFailedNotification.Cancel) { authFailedEx.Throw(); } } else { authFailedEx.Throw(); } } } } return(null); }