/// <summary> /// Create an authenticate request aimed for this idp. /// </summary> /// <param name="returnUrl">The return url where the browser should be sent after /// successful authentication.</param> /// <param name="authServicesUrls">Urls for AuthServices, used to populate fields /// in the created AuthnRequest</param> /// <param name="relayData">Aux data that should be preserved across the authentication</param> /// <returns>AuthnRequest</returns> public Saml2AuthenticationRequest CreateAuthenticateRequest( Uri returnUrl, AuthServicesUrls authServicesUrls, object relayData) { if (authServicesUrls == null) { throw new ArgumentNullException("authServicesUrls"); } var authnRequest = new Saml2AuthenticationRequest() { DestinationUrl = SingleSignOnServiceUrl, AssertionConsumerServiceUrl = authServicesUrls.AssertionConsumerServiceUrl, Issuer = spOptions.EntityId, // For now we only support one attribute consuming service. AttributeConsumingServiceIndex = spOptions.AttributeConsumingServices.Any() ? 0 : (int?)null }; var responseData = new StoredRequestState(EntityId, returnUrl, relayData); PendingAuthnRequests.Add(new Saml2Id(authnRequest.Id), responseData); return(authnRequest); }
public void AuthServicesUrls_Ctor_AllowsNullAcs() { // AssertionConsumerServiceURL is optional in the SAML spec var subject = new AuthServicesUrls(null, new Uri("http://localhost/signin")); subject.AssertionConsumerServiceUrl.Should().Be(null); subject.SignInUrl.ToString().Should().Be("http://localhost/signin"); }
public void AuthServiecsUrls_Ctor_AcceptsFullUrls() { var acsUrl = new Uri("http://localhost:73/MyApp/MyAcs"); var signinUrl = new Uri("http://localhost:73/MyApp/MySignin"); var subject = new AuthServicesUrls(acsUrl, signinUrl); subject.AssertionConsumerServiceUrl.ToString().Should().Be(acsUrl.ToString()); subject.SignInUrl.ToString().Should().Be(signinUrl.ToString()); }
public void AuthServicesUrls_Ctor_HandlesApplicationInRoot() { var appUrl = new Uri("http://localhost:42/"); var modulePath = "/modulePath"; var subject = new AuthServicesUrls(appUrl, modulePath); subject.AssertionConsumerServiceUrl.Should().Be(new Uri("http://localhost:42/modulePath/Acs")); subject.SignInUrl.Should().Be(new Uri("http://localhost:42/modulePath/SignIn")); }
public async Task AuthServicesUrls_Ctor_FromOwinHttpRequestData_PublicOrigin() { var ctx = OwinTestHelpers.CreateOwinContext(); var options = StubFactory.CreateOptionsPublicOrigin(new Uri("https://my.public.origin:8443/")); var subject = await ctx.ToHttpRequestData(null); var urls = new AuthServicesUrls(subject, options); urls.AssertionConsumerServiceUrl.ShouldBeEquivalentTo("https://my.public.origin:8443/AuthServices/Acs"); urls.SignInUrl.ShouldBeEquivalentTo("https://my.public.origin:8443/AuthServices/SignIn"); }
public void AuthServicesUrls_Ctor_PerRequest_PublicOrigin() { var options = StubFactory.CreateOptionsPublicOrigin(new Uri("https://my.public.origin:8443/")); options.Notifications.GetPublicOrigin = (requestData) => { return(new Uri("https://special.public.origin/")); }; var urls = new AuthServicesUrls(new HttpRequestData("get", new Uri("http://servername/")), options); urls.AssertionConsumerServiceUrl.ShouldBeEquivalentTo("https://special.public.origin/AuthServices/Acs"); urls.SignInUrl.ShouldBeEquivalentTo("https://special.public.origin/AuthServices/SignIn"); }
public void AuthServicesUrls_Ctor_EnsuresApplicationUrlEndsWithSlash() { var request = new HttpRequestData( "GET", new Uri("http://localhost:1234/Foo/Bar"), "/Foo", null, null, null); var options = StubFactory.CreateOptions(); var subject = new AuthServicesUrls(request, options); subject.ApplicationUrl.OriginalString.Should().EndWith("/"); }
public Saml2AuthenticationRequest CreateAuthenticateRequest( Uri returnUrl, AuthServicesUrls authServicesUrls, object relayData) { if (authServicesUrls == null) { throw new ArgumentNullException(nameof(authServicesUrls)); } var authnRequest = new Saml2AuthenticationRequest() { DestinationUrl = SingleSignOnServiceUrl, AssertionConsumerServiceUrl = authServicesUrls.AssertionConsumerServiceUrl, Issuer = spOptions.EntityId, // For now we only support one attribute consuming service. AttributeConsumingServiceIndex = spOptions.AttributeConsumingServices.Any() ? 0 : (int?)null, NameIdPolicy = spOptions.NameIdPolicy, RequestedAuthnContext = spOptions.RequestedAuthnContext }; if (spOptions.AuthenticateRequestSigningBehavior == SigningBehavior.Always || (spOptions.AuthenticateRequestSigningBehavior == SigningBehavior.IfIdpWantAuthnRequestsSigned && WantAuthnRequestsSigned)) { if (spOptions.SigningServiceCertificate == null) { throw new ConfigurationErrorsException( string.Format( CultureInfo.InvariantCulture, "Idp \"{0}\" is configured for signed AuthenticateRequests, but ServiceCertificates configuration contains no certificate with usage \"Signing\" or \"Both\".", EntityId.Id)); } authnRequest.SigningCertificate = spOptions.SigningServiceCertificate; } var requestState = new StoredRequestState(EntityId, returnUrl, authnRequest.Id, relayData); PendingAuthnRequests.Add(authnRequest.RelayState, requestState); return(authnRequest); }
public void AuthServicesUrls_Ctor_FromHttpRequest_PublicOrigin() { var url = new Uri("http://example.com:42/ApplicationPath/Path?name=DROP%20TABLE%20STUDENTS"); string appPath = "/ApplicationPath"; var request = Substitute.For <HttpRequestBase>(); request.HttpMethod.Returns("GET"); request.Url.Returns(url); request.Form.Returns(new NameValueCollection { { "Key", "Value" } }); request.ApplicationPath.Returns(appPath); var options = StubFactory.CreateOptionsPublicOrigin(new Uri("https://my.public.origin:8443/OtherPath")); var subject = request.ToHttpRequestData(); var urls = new AuthServicesUrls(subject, options); urls.AssertionConsumerServiceUrl.ShouldBeEquivalentTo("https://my.public.origin:8443/OtherPath/AuthServices/Acs"); urls.SignInUrl.ShouldBeEquivalentTo("https://my.public.origin:8443/OtherPath/AuthServices/SignIn"); }
/// <summary> /// Create an authenticate request aimed for this idp. /// </summary> /// <param name="authServicesUrls">Urls for AuthServices, used to populate fields /// in the created AuthnRequest</param> /// <returns>AuthnRequest</returns> public Saml2AuthenticationRequest CreateAuthenticateRequest( AuthServicesUrls authServicesUrls) { if (authServicesUrls == null) { throw new ArgumentNullException("authServicesUrls"); } var authnRequest = new Saml2AuthenticationRequest() { DestinationUrl = SingleSignOnServiceUrl, AssertionConsumerServiceUrl = authServicesUrls.AssertionConsumerServiceUrl, Issuer = spOptions.EntityId, // For now we only support one attribute consuming service. AttributeConsumingServiceIndex = spOptions.AttributeConsumingServices.Any() ? 0 : (int?)null }; return(authnRequest); }
protected async override Task ApplyResponseGrantAsync() { var revoke = Helper.LookupSignOut(Options.AuthenticationType, Options.AuthenticationMode); if (revoke != null) { var request = await Context.ToHttpRequestData(Options.DataProtector.Unprotect); var urls = new AuthServicesUrls(request, Options.SPOptions); string redirectUrl = revoke.Properties.RedirectUri; if (string.IsNullOrEmpty(redirectUrl)) { if (Context.Response.StatusCode / 100 == 3) { var locationUrl = Context.Response.Headers["Location"]; redirectUrl = new Uri( new Uri(urls.ApplicationUrl.ToString().TrimEnd('/') + Context.Request.Path), locationUrl ).ToString(); } else { redirectUrl = new Uri( urls.ApplicationUrl, Context.Request.Path.ToUriComponent().TrimStart('/')) .ToString(); } } var result = LogoutCommand.Run(request, redirectUrl, Options); if (!result.HandledResult) { result.Apply(Context, Options.DataProtector); } } await AugmentAuthenticationGrantWithLogoutClaims(Context); }
static CommandResult CreateResult( EntityId idpEntityId, string returnPath, HttpRequestData request, IOptions options, object relayData = null) { var urls = new AuthServicesUrls(request, options.SPOptions); IdentityProvider idp; if (idpEntityId == null || idpEntityId.Id == null) { //if (options.SPOptions.DiscoveryServiceUrl != null) //{ // return RedirectToDiscoveryService(returnPath, options.SPOptions, urls); //} idp = options.IdentityProviders.Default; } else { if (!options.IdentityProviders.TryGetValue(idpEntityId, out idp)) { throw new InvalidOperationException("Unknown idp"); } } Uri returnUrl = null; if (!string.IsNullOrEmpty(returnPath)) { Uri.TryCreate(request.Url, returnPath, out returnUrl); } var authnRequest = idp.CreateAuthenticateRequest(returnUrl, urls, relayData); return(idp.Bind(authnRequest)); }
protected async override Task ApplyResponseGrantAsync() { // Automatically sign out, even if passive because passive sign in and auto sign out // is typically most common scenario. Unless strict compatibility is set. var mode = Options.SPOptions.Compatibility.StrictOwinAuthenticationMode ? Options.AuthenticationMode : AuthenticationMode.Active; var revoke = Helper.LookupSignOut(Options.AuthenticationType, mode); if (revoke != null) { var request = await Context.ToHttpRequestData(Options.DataProtector.Unprotect); var urls = new AuthServicesUrls(request, Options); string redirectUrl = revoke.Properties.RedirectUri; if (string.IsNullOrEmpty(redirectUrl)) { if (Context.Response.StatusCode / 100 == 3) { redirectUrl = Context.Response.Headers["Location"]; } else { redirectUrl = Context.Request.Path.ToUriComponent(); } } var result = LogoutCommand.Run(request, redirectUrl, Options); if (!result.HandledResult) { result.Apply(Context, Options.DataProtector); } } await AugmentAuthenticationGrantWithLogoutClaims(Context); }
public Saml2AuthenticationRequest CreateAuthenticateRequest( AuthServicesUrls authServicesUrls) { if (authServicesUrls == null) { throw new ArgumentNullException(nameof(authServicesUrls)); } var authnRequest = new Saml2AuthenticationRequest() { DestinationUrl = SingleSignOnServiceUrl, AssertionConsumerServiceUrl = authServicesUrls.AssertionConsumerServiceUrl, Issuer = spOptions.EntityId, // For now we only support one attribute consuming service. AttributeConsumingServiceIndex = spOptions.AttributeConsumingServices.Any() ? 0 : (int?)null, NameIdPolicy = spOptions.NameIdPolicy, RequestedAuthnContext = spOptions.RequestedAuthnContext, SigningAlgorithm = this.OutboundSigningAlgorithm }; if (spOptions.AuthenticateRequestSigningBehavior == SigningBehavior.Always || (spOptions.AuthenticateRequestSigningBehavior == SigningBehavior.IfIdpWantAuthnRequestsSigned && WantAuthnRequestsSigned)) { if (spOptions.SigningServiceCertificate == null) { throw new ConfigurationErrorsException( string.Format( CultureInfo.InvariantCulture, "Idp \"{0}\" is configured for signed AuthenticateRequests, but ServiceCertificates configuration contains no certificate with usage \"Signing\" or \"Both\". To resolve this issue you can a) add a service certificate with usage \"Signing\" or \"Both\" (default if not specified is \"Both\") or b) Set the AuthenticateRequestSigningBehavior configuration property to \"Never\".", EntityId.Id)); } authnRequest.SigningCertificate = spOptions.SigningServiceCertificate; } return(authnRequest); }
public static ExtendedEntityDescriptor CreateMetadata(this ISPOptions spOptions, AuthServicesUrls urls) { var ed = new ExtendedEntityDescriptor { EntityId = spOptions.EntityId, Organization = spOptions.Organization, CacheDuration = spOptions.MetadataCacheDuration }; foreach (var contact in spOptions.Contacts) { ed.Contacts.Add(contact); } var spsso = new ExtendedServiceProviderSingleSignOnDescriptor(); spsso.ProtocolsSupported.Add(new Uri("urn:oasis:names:tc:SAML:2.0:protocol")); spsso.AssertionConsumerServices.Add(0, new IndexedProtocolEndpoint() { Index = 0, IsDefault = true, Binding = Saml2Binding.HttpPostUri, Location = urls.AssertionConsumerServiceUrl }); spsso.AssertionConsumerServices.Add(1, new IndexedProtocolEndpoint() { Index = 1, IsDefault = false, Binding = Saml2Binding.HttpArtifactUri, Location = urls.AssertionConsumerServiceUrl }); foreach (var attributeService in spOptions.AttributeConsumingServices) { spsso.AttributeConsumingServices.Add(attributeService); } if (spOptions.ServiceCertificates != null) { var publishCertificates = spOptions.MetadataCertificates; foreach (var serviceCert in publishCertificates) { using (var securityToken = new X509SecurityToken(serviceCert.Certificate)) { spsso.Keys.Add( new KeyDescriptor { Use = (KeyType)(byte)serviceCert.Use, KeyInfo = new SecurityKeyIdentifier(securityToken.CreateKeyIdentifierClause <X509RawDataKeyIdentifierClause>()) } ); } } } if (spOptions.DiscoveryServiceUrl != null && !string.IsNullOrEmpty(spOptions.DiscoveryServiceUrl.OriginalString)) { spsso.Extensions.DiscoveryResponse = new IndexedProtocolEndpoint { Binding = Saml2Binding.DiscoveryResponseUri, Index = 0, IsDefault = true, Location = urls.SignInUrl }; } ed.RoleDescriptors.Add(spsso); return(ed); }
/// <summary> /// Create an authenticate request aimed for this idp. /// </summary> /// <param name="returnUrl">The return url where the browser should be sent after /// successful authentication.</param> /// <param name="authServicesUrls">Urls for AuthServices, used to populate fields /// in the created AuthnRequest</param> /// <returns>AuthnRequest</returns> public Saml2AuthenticationRequest CreateAuthenticateRequest( Uri returnUrl, AuthServicesUrls authServicesUrls) { return(CreateAuthenticateRequest(returnUrl, authServicesUrls, null)); }
public static ExtendedEntityDescriptor CreateMetadata(this ISPOptions spOptions, AuthServicesUrls urls) { var ed = new ExtendedEntityDescriptor { EntityId = spOptions.EntityId, Organization = spOptions.Organization, CacheDuration = spOptions.MetadataCacheDuration }; foreach (var contact in spOptions.Contacts) { ed.Contacts.Add(contact); } var spsso = new ExtendedServiceProviderSingleSignOnDescriptor(); spsso.ProtocolsSupported.Add(new Uri("urn:oasis:names:tc:SAML:2.0:protocol")); spsso.AssertionConsumerServices.Add(0, new IndexedProtocolEndpoint() { Index = 0, IsDefault = true, Binding = Saml2Binding.HttpPostUri, Location = urls.AssertionConsumerServiceUrl }); foreach (var attributeService in spOptions.AttributeConsumingServices) { spsso.AttributeConsumingServices.Add(attributeService); } ed.RoleDescriptors.Add(spsso); if (spOptions.DiscoveryServiceUrl != null && !string.IsNullOrEmpty(spOptions.DiscoveryServiceUrl.OriginalString)) { ed.Extensions.DiscoveryResponse = new IndexedProtocolEndpoint { Binding = Saml2Binding.DiscoveryResponseUri, Index = 0, IsDefault = true, Location = urls.SignInUrl }; } return(ed); }