private string HandleSignOut(HttpContext context, SamlRequestMessage message, string issuer, IDictionary <string, string> parameters, string logoutUrl) { var handler = CreateSessionHandler(); handler.ClearEndpoints(context); var samlResponse = new SamlResponseMessage(); samlResponse.Id = Guid.NewGuid().ToString(); samlResponse.InResponseTo = message.Id; samlResponse.Issuer = issuer; samlResponse.ReplyTo = new Uri(logoutUrl); samlResponse.ResponseType = "LogoutResponse"; var sb = new StringBuilder(); using (var xmlWriter = XmlWriter.Create(new StringWriter(sb))) { _serializer.Serialize(xmlWriter, samlResponse); } var form = BuildSignInFormPost(logoutUrl, sb.ToString(), null); return(form); }
private async Task <string> HandleSignIn(HttpContext context, SamlRequestMessage message, string issuer, IDictionary <string, string> parameters, string replyUrl) { var handler = CreateSessionHandler(); var request = new SignInRequest { User = context.User, Realm = message.Issuer, Parameters = parameters }; var response = await _responseGenerator.GenerateSignInResponse(request); handler.AddRealm(context, message.Issuer); var samlResponse = new SamlResponseMessage(); samlResponse.Token = response.Token; samlResponse.Id = Guid.NewGuid().ToString(); samlResponse.InResponseTo = (!string.IsNullOrWhiteSpace(message.Id)) ? message.Id : Guid.NewGuid().ToString(); samlResponse.ReplyTo = new Uri(replyUrl); samlResponse.Issuer = issuer; samlResponse.ResponseType = "Response"; var sb = new StringBuilder(); using (var xmlWriter = XmlWriter.Create(new StringWriter(sb))) { _serializer.Serialize(xmlWriter, samlResponse); } var form = BuildSignInFormPost(replyUrl, sb.ToString(), message.RelayState); return(form); }
public async Task Invoke(HttpContext context) { var segment = _options.Saml20Endpoint; var idpInitiatedSegment = $"{segment}/idpinitiated"; if (context.Request.Path.StartsWithSegments(new PathString(segment), StringComparison.InvariantCultureIgnoreCase)) { if (!( context.Request.Method.Equals("POST", StringComparison.InvariantCultureIgnoreCase) || context.Request.Method.Equals("GET", StringComparison.InvariantCultureIgnoreCase)) ) { context.Response.StatusCode = (int)HttpStatusCode.MethodNotAllowed; return; } _logger.LogInformation("Received SAML 2.0 Request. {0}", context.Request.QueryString.ToUriComponent()); if (context.Request.Path.StartsWithSegments(idpInitiatedSegment)) { if (!context.Request.Query.ContainsKey("realm")) { _logger.LogWarning("Invalid message. IDP Initiated with no realm"); context.Response.StatusCode = (int)HttpStatusCode.BadRequest; await context.Response.WriteAsync($"Invalid message. IDP Initiated with no realm"); return; } } else if ((context.Request.Method == "GET" && !context.Request.Query.ContainsKey("SAMLRequest")) || (context.Request.Method == "POST" && !context.Request.Form.ContainsKey("SAMLRequest"))) { _logger.LogWarning("Invalid message. It does not contain SAMLRequest"); context.Response.StatusCode = (int)HttpStatusCode.BadRequest; await context.Response.WriteAsync($"Invalid SAMLRequest Request Message"); return; } SamlRequestMessage message = null; if (context.Request.Path.StartsWithSegments(idpInitiatedSegment)) { message = new SamlRequestMessage( Guid.NewGuid().ToString(), context.Request.Query["realm"], context.Request.Query["relayState"], true); } else { if (context.Request.Method.Equals("GET", StringComparison.InvariantCultureIgnoreCase)) { var samlRequest = context.Request.Query["SAMLRequest"]; _logger.LogWarning("Processing SAMLRequest from GET"); message = SamlRequestMessage.CreateFromCompressedRequest(samlRequest, context.Request.Query["relayState"]); } else { var samlRequest = context.Request.Form["SAMLRequest"]; _logger.LogWarning("Processing SAMLRequest from POST"); message = SamlRequestMessage.CreateFromEncodedRequest(samlRequest, context.Request.Form["relayState"]); } } if (!context.User.Identity.IsAuthenticated) { _logger.LogInformation("User is not authenticated. Redirecting to authentication provider"); var qs = context.Request.QueryString; var url = $"{context.Request.Scheme}://{context.Request.Host}{context.Request.PathBase}{idpInitiatedSegment}/?realm={message.Issuer}&relayState={message.RelayState}"; await context.ChallengeAsync(new AuthenticationProperties { RedirectUri = url }); return; } var relyingParty = await _relyingPartyStore.GetByRealm(message.Issuer); if (relyingParty == null) { _logger.LogWarning("No relying party found for realm {0}", message.Issuer); context.Response.StatusCode = (int)HttpStatusCode.BadRequest; await context.Response.WriteAsync($"{message.Issuer} is not registered"); return; } var parameters = context.Request.Query.ToDictionary(q => q.Key, q => q.Value[0]); if (message.IsSignInMessage) { _logger.LogWarning("Processing SAML Sign In for relying party with realm {0}", message.Issuer); var output = await HandleSignIn(context, message, _options.IssuerName, parameters, relyingParty.ReplyUrl); context.Response.ContentType = "text/html"; await context.Response.WriteAsync(output); return; } else { _logger.LogWarning("Processing SAML Sign out for relying party with realm {0}", message.Issuer); var output = HandleSignOut(context, message, _options.IssuerName, parameters, relyingParty.LogoutUrl); context.Response.ContentType = "text/html"; await context.Response.WriteAsync(output); return; } } await _next(context); }