Web Browser SSO Profile (SAML 2.0)
The SAML authentication flow allows users to authenticate using their identity provider (IdP) credentials. This component implements the standard SAML 2.0 Web Browser SSO Profile with support for both SP-initiated and IdP-initiated flows.
SAML authentication sequence diagram
Parameter | Type | Required | Default | Description |
---|---|---|---|---|
idpMetadataUrl | string | Yes | - | URL to the IdP metadata XML |
spEntityId | string | Yes | - | Service Provider entity ID |
assertEndpoint | string | Yes | - | Assertion consumer service URL |
nameIdFormat | string | No | urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified | Format for NameID |
authnContext | string | No | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport | Authentication context class |
const samlAuth = new SAMLAuthentication({
// Required configuration
idpMetadataUrl: 'https://idp.example.com/metadata.xml',
spEntityId: 'urn:example:sp',
assertEndpoint: 'https://your-app.com/saml/acs',
// Optional configuration
name极IdFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
authnContext: 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport',
forceAuthn: false,
allowCreate: true,
requestBinding: 'HTTP-Redirect',
responseBinding: 'HTTP-POST'
});
// Initiate SP-initiated login
app.get('/login', (req, res) => {
samlAuth.login(req, res, {
// Optional parameters
RelayState: '/dashboard',
AuthnRequestExtensions: '<my:CustomAttribute>value</my:CustomAttribute>'
});
});
// Handle assertion response
app.post('/saml/acs', (req, res) => {
samlAuth.handleAssertion(req, res)
.then(user => {
// User authenticated successfully
req.session.user = user;
res.redirect(req.body.RelayState || '/');
})
.catch(err => {
// Handle authentication failure
console.error('SAML authentication failed:', err);
res.status(401).render('error', {
message: 'Authentication failed',
details: err.message
});
});
});
// Metadata endpoint
app.get('/saml/metadata', (req, res) => {
res.type('application/xml');
res.send(samlAuth.generateMetadata());
});
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${saml.idp.metadata}")
private String idpMetadataUrl;
@Bean
public SAMLAuthenticationProvider samlAuthenticationProvider() {
return new SAMLAuthenticationProvider();
}
@Bean
public SAMLMetadataFilter metadataFilter() {
return new SAMLMetadataFilter();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/saml/**").permitAll()
.anyRequest().authenticated()
.and()
.apply(new SAMLConfigurer())
.idpMetadataUrl(idpMetadataUrl)
.spEntityId("urn:example:sp")
.assertionConsumerServiceUrl("/saml/acs")
.and()
.addFilterBefore(metadataFilter(),
UsernamePasswordAuthenticationFilter.class);
}
}
from flask import Flask, request, redirect, session
from flask_saml import SAMLAuthentication
app = Flask(__name__)
app.secret_key = 'your-secret-key'
saml_auth = SAMLAuthentication(
app,
idp_metadata_url='https://idp.example.com/metadata.xml',
sp_entity_id='urn:example:sp',
acs_url='/saml/acs'
)
@app.route('/login')
def login():
return saml_auth.login(relay_state='/dashboard')
@app.route('/saml/acs', methods=['POST'])
def acs():
user = saml_auth.process_response()
session['user'] = user
return redirect(request.form.get('RelayState', '/'))
@app.route('/saml/metadata')
def metadata():
return saml_auth.generate_metadata()
Implement SAML Single Logout (SLO) for session termination
Map SAML attributes to user profile fields
Configure security policies for SAML assertions