浏览代码

SAML 2 Login - Documentation

Fixes gh-7472
https://github.com/spring-projects/spring-security/issues/7472
Filip Hanik 6 年之前
父节点
当前提交
8bc3ad16ef

+ 2 - 0
docs/manual/src/docs/asciidoc/_includes/servlet/index.adoc

@@ -12,6 +12,8 @@ include::authorization/index.adoc[leveloffset=+1]
 
 include::oauth2/index.adoc[leveloffset=+1]
 
+include::saml2/index.adoc[leveloffset=+1]
+
 include::exploits/index.adoc[leveloffset=+1]
 
 include::integrations/index.adoc[leveloffset=+1]

+ 3 - 0
docs/manual/src/docs/asciidoc/_includes/servlet/saml2/index.adoc

@@ -0,0 +1,3 @@
+= SAML2
+
+include::saml2-login.adoc[]

+ 312 - 0
docs/manual/src/docs/asciidoc/_includes/servlet/saml2/saml2-login.adoc

@@ -0,0 +1,312 @@
+[[saml2login]]
+== SAML 2.0 Login
+
+The SAML 2.0 Login, `saml2Login()`, feature provides an application with the capability to have users log in to the application by using their existing account at an SAML 2.0 Identity Provider (Okta, ADFS, etc).
+
+NOTE: SAML 2.0 Login is implemented by using the *Web Browser SSO Profile*, as specified in
+https://www.oasis-open.org/committees/download.php/35389/sstc-saml-profiles-errata-2.0-wd-06-diff.pdf#page=15[SAML 2 Profiles].
+Our implementation is currently limited to a simple authentication scheme.
+
+[[saml2login-spring-security-saml2-history]]
+=== SAML 2 Support in Spring Security
+
+SAML 2 Service Provider, SP a.k.a. a relying party, support existed as an
+https://github.com/spring-projects/spring-security-saml/tree/1e013b07a7772defd6a26fcfae187c9bf661ee8f#spring-saml[independent project]
+since 2009. The 1.0.x branch is still in use, including in the
+https://github.com/cloudfoundry/uaa[Cloud Foundry User Account and Authentication Server] that
+also created a SAML 2.0 Identity Provider implementation based on the SP implementation.
+
+In 2018 we experimented with creating an updated implementation of both a
+https://github.com/spring-projects/spring-security-saml#spring-saml[Service Provider and Identity Provider]
+as a standalone library. After careful, and lengthy, deliberation we, the Spring Security team, decided
+to discontinue that effort. While this effort created a replacement for that standalone 1.0.x library
+we didn't feel that we should build a library on top of another library.
+
+Instead we opted to provide framework support for SAML 2 authentication as part of
+https://github.com/spring-projects/spring-security[core Spring Security] instead.
+
+[[samllogin-concepts]]
+=== Saml 2 Login - High Level Concepts
+
+`saml2Login()` is aimed to support a fraction of the https://saml.xml.org/saml-specifications[SAML 2 feature set]
+with a focus on authentication being a Service Provider, SP, a relying party, receiving XML assertions from an
+Identity Provider, aka an asserting party.
+
+A SAML 2 login, or authentication, is the concept that the SP receives and validates an XML message called
+an assertion from an IDP.
+
+There are currently two supported authentication flows
+
+1. IDP Initiated flow - example: You login in directly to Okta, and then select a web application to be authenticated for.
+Okta, the IDP, sends an assertion to the web application, the SP.
+2. SP Initiated flow - example: You access a web application, a SP, the application sends an
+authentication request to the IDP requesting an assertion. Upon successful authentication on the IDP,
+the IDP sends an assertion to the SP.
+
+[[samllogin-feature-set]]
+=== Saml 2 Login - Current Feature Set
+
+1. Service Provider (SP/Relying Party) is identified by `entityId = {baseUrl}/saml2/service-provider-metadata/{registrationId}`
+2. Receive assertion embedded in a SAML response via Http-POST or Http-Redirect at `{baseUrl}/login/saml2/sso/{registrationId}`
+3. Requires the assertion to be signed, unless the response is signed
+4. Supports encrypted assertions
+5. Supports encrypted NameId elements
+6. Allows for extraction of assertion attributes into authorities using a `Converter<Assertion, Collection<? extends GrantedAuthority>>`
+7. Allows mapping and white listing of authorities using a `GrantedAuthoritiesMapper`
+8. Public keys in `java.security.cert.X509Certificate` format.
+9. SP Initiated Authentication via an `AuthNRequest`
+
+==== Saml 2 Login - Not Yet Supported
+
+1. Mappings assertion conditions and attributes to session features (timeout, tracking, etc)
+2. Single logout
+3. Dynamic metadata generation
+4. Receiving and validating standalone assertion (not wrapped in a response object)
+
+[[samllogin-introduction-java-config]]
+=== Saml 2 Login - Introduction to Java Configuration
+
+To add `saml2Login()` to a Spring Security filter chain,
+the minimal Java configuration requires a configuration repository,
+the `RelyingPartyRegistrationRepository`, that contains the SAML configuration and
+the invocation of the `HttpSecurity.saml2Login()` method:
+[source,java]
+----
+@EnableWebSecurity
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+    @Bean
+    public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() {
+        //SAML configuration
+        //Mapping this application to one or more Identity Providers
+        return new InMemoryRelyingPartyRegistrationRepository(...);
+    }
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        http
+            .authorizeRequests()
+                .anyRequest().authenticated()
+                .and()
+            .saml2Login()
+        ;
+    }
+}
+----
+
+The bean declaration is a convenient, but optional, approach.
+You can directly wire up the repository using a method call
+[source,java]
+----
+@EnableWebSecurity
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        http
+            .authorizeRequests()
+                .anyRequest().authenticated()
+                .and()
+            .saml2Login()
+                .relyingPartyRegistrationRepository(...)
+        ;
+    }
+}
+----
+
+==== RelyingPartyRegistration
+The https://github.com/spring-projects/spring-security/blob/5.2.0.RELEASE/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java[`RelyingPartyRegistration`]
+object represents the mapping between this application, the SP, and the asserting party, the IDP.
+
+===== URI Patterns
+
+URI patterns are frequenty used to automatically generate URIs based on
+an incoming request. The URI patterns in `saml2Login` can contain the following variables
+
+* `baseUrl`
+* `registrationId`
+* `baseScheme`
+* `baseHost`
+* `basePort`
+
+For example:
+```
+{baseUrl}/login/saml2/sso/{registrationId}
+```
+
+===== Relying Party
+
+
+* `registrationId` - (required) a unique identifer for this configuration mapping.
+This identifier may be used in URI paths, so care should be taken that no URI encoding is required.
+* `localEntityIdTemplate` - (optional) A URI pattern that creates an entity ID for this application based on the incoming request. The default is
+`{baseUrl}/saml2/service-provider-metadata/{registrationId}` and for a small sample application
+it would look like
+```
+http://localhost:8080/saml2/service-provider-metadata/my-test-configuration
+```
+There is no requirement that this configuration option is a pattern, it can be a fixed URI value.
+
+* `remoteIdpEntityId` - (required) the entity ID of the Identity Provider. Always a fixed URI value or string,
+no patterns allowed.
+* `assertionConsumerServiceUrlTemplate` - (optional) A URI pattern that denotes the assertion
+consumer service URI to be sent with any `AuthNRequest` from the SP to the IDP during the SP initiated flow.
+While this can be a pattern the actual URI must resolve to the ACS endpoint on the SP.
+The default value is `{baseUrl}/login/saml2/sso/{registrationId}` and maps directly to the
+https://github.com/spring-projects/spring-security/blob/5.2.0.RELEASE/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilter.java#L42[`Saml2WebSsoAuthenticationFilter`] endpoint
+* `idpWebSsoUrl`  - (required) a fixed URI value for the IDP Single Sign On endpoint where
+the SP sends the `AuthNRequest` messages.
+* `credentials` - A list of credentials, private keys and x509 certificates, used for
+message signing, verification, encryption and decryption.
+This list can contain redundant credentials to allow for easy rotation of credentials.
+For example
+** [0] - X509Certificate{VERIFICATION,ENCRYPTION} - The IDP's first public key used for
+verification and encryption.
+** [1] - X509Certificate/{VERIFICATION,ENCRYPTION} - The IDP's second verification key used for verification.
+Encryption is always done using the first `ENCRYPTION` key in the list.
+** [2] - PrivateKey/X509Certificate{SIGNING,DECRYPTION} - The SP's first signing and decryption credential.
+** [3] - PrivateKey/X509Certificate{SIGNING,DECRYPTION} - The SP's second decryption credential.
+Signing is always done using the first `SIGNING` key in the list.
+
+When an incoming message is received, signatures are always required, the system will first attempt
+to validate the signature using the certificate at index [0] and only move to the second
+credential if the first one fails.
+
+In a similar fashion, the SP configured private keys are used for decryption and attempted in the same order.
+The first SP credential (`type=SIGNING`) will be used when messages to the IDP are signed.
+
+===== Duplicated Relying Party Configurations
+
+In the use case where an application uses multiple identity providers it becomes
+obvious that some configuration is duplicated between two `RelyingPartyRegistration` objects
+
+* localEntityIdTemplate
+* credentials (all SP credentials, IDP credentials change)
+* assertionConsumerServiceUrlTemplate
+
+While there is some drawback in duplicating configuration values the back end
+configuration repository does not need to replicate this data storage model.
+
+There is a benefit that comes with this setup. Credentials may be more easily rotated
+for some identity providers vs others. This object model can ensure that there is no
+disruption when configuration is changed in a multi IDP use case and you're not able to rotate
+credentials on all the identity providers.
+
+==== Service Provider Metadata
+
+The Spring Security SAML 2 implementation does not yet provide an endpoint for downloading
+SP metadata in XML format. The minimal pieces that are exchanged
+
+* *entity ID* - defaults to `{baseUrl}/saml2/service-provider-metadata/{registrationId}`
+Other known configuration names that also use this same value
+** Audience Restriction
+* *single signon URL* - defaults to `{baseUrl}/login/saml2/sso/{registrationId}`
+Other known configuration names that also use this same value
+** Recipient URL
+** Destination URL
+** Assertion Consumer Service URL
+* X509Certificate - the certificate that you configure as part of your {SIGNING,DECRYPTION}
+credentials must be shared with the Identity Provider
+
+==== Authentication Requests - SP Initiated Flow
+
+To initiate an authentication from the web application, a simple redirect to
+```
+{baseUrl}/saml2/authenticate/{registrationId}
+```
+The endpoint will generate an `AuthNRequest` by invoking the `createAuthenticationRequest` method on a
+configurable factory. Just expose the `Saml2AuthenticationRequestFactory` as a bean in your configuration.
+[source,java]
+----
+public interface Saml2AuthenticationRequestFactory {
+    String createAuthenticationRequest(Saml2AuthenticationRequest request);
+}
+----
+
+[[samllogin-sample-boot]]
+=== Spring Boot 2.x Sample
+
+We are currently working with the the Spring Boot team on the
+https://github.com/spring-projects/spring-boot/issues/18260[Auto Configuration for Spring Security SAML Login].
+In the meantime, we have provided a Spring Boot sample that supports a Yaml configuration.
+
+To run the sample, follow these three steps
+
+1. Launch the Spring Boot application
+** `./gradlew :spring-security-samples-boot-saml2login:bootRun`
+2. Open a browser
+** http://localhost:8080/[http://localhost:8080/]
+3. This will take you to an identity provider, log in using:
+** User: `user`
+** Password: `password`
+
+==== Multiple Identity Provider Sample
+
+It's very simple to use multiple providers, but there are some defaults that
+may trip you up if you don't pay attention. In our SAML configuration of
+`RelyingPartyRegistration` objects, we default an SP entity ID to
+```
+{baseUrl}/saml2/service-provider-metadata/{registrationId}
+```
+
+That means in our two provider configuration, our system would look like
+
+```
+registration-1 (Identity Provider 1) - Our local SP Entity ID is:
+http://localhost:8080/saml2/service-provider-metadata/registration-1
+
+registration-2 (Identity Provider 2) - Our local SP Entity ID is:
+http://localhost:8080/saml2/service-provider-metadata/registration-2
+```
+
+In this configuration, illustrated in the sample below, to the outside world,
+we have actually created two virtual Service Provider identities
+hosted within the same application.
+
+[source,yaml]
+----
+spring:
+  security:
+    saml2:
+      login:
+        relying-parties:
+          - entity-id: &idp-entity-id https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/metadata.php
+            registration-id: simplesamlphp
+            web-sso-url: &idp-sso-url https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php
+            signing-credentials: &service-provider-credentials
+              - private-key: |
+                  -----BEGIN PRIVATE KEY-----
+                  MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANG7v8QjQGU3MwQE
+                  ...................SHORTENED FOR READ ABILITY...................
+                  INrtuLp4YHbgk1mi
+                  -----END PRIVATE KEY-----
+                certificate: |
+                  -----BEGIN CERTIFICATE-----
+                  MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMC
+                  ...................SHORTENED FOR READ ABILITY...................
+                  RZ/nbTJ7VTeZOSyRoVn5XHhpuJ0B
+                  -----END CERTIFICATE-----
+            verification-credentials: &idp-certificates
+              - |
+                -----BEGIN CERTIFICATE-----
+                MIIEEzCCAvugAwIBAgIJAIc1qzLrv+5nMA0GCSqGSIb3DQEBCwUAMIGfMQswCQYD
+                ...................SHORTENED FOR READ ABILITY...................
+                lx13Y1YlQ4/tlpgTgfIJxKV6nyPiLoK0nywbMd+vpAirDt2Oc+hk
+                -----END CERTIFICATE-----
+          - entity-id: *idp-entity-id
+            registration-id: simplesamlphp2
+            web-sso-url: *idp-sso-url
+            signing-credentials: *service-provider-credentials
+            verification-credentials: *idp-certificates
+----
+
+If this is not desirable, you can manually override the local SP entity ID by using the
+```
+localEntityIdTemplate = {baseUrl}/saml2/service-provider-metadata
+```
+If we change our local SP entity ID to this value, it is still important that we give
+out the correct single sign on URL (the assertion consumer service URL)
+for each registered identity provider based on the registration Id.
+`{baseUrl}/login/saml2/sso/{registrationId}`
+
+