JAX, Mainz 7.5.2019
Slides: https://andifalk.github.io/jax-2019-openid-connect-spring-security
Demos: https://github.com/andifalk/jax-2019-openid-connect-spring-security
Novatec Consulting GmbH
andreas.falk@novatec-gmbh.de / @andifalk (Twitter)Intro to OAuth 2.0 & OpenID Connect 1.0
Current Discussions & Best Practices in OAuth 2.0/OIDC
OAuth 2 & OIDC with Spring Security 5 (Live Demo)
RFC 6749: The OAuth 2.0 Authorization Framework
RFC 6750: OAuth 2.0 Bearer Token Usage
RFC 6819: OAuth 2.0 Threat Model and Security Considerations
OAuth 2.0 is an authorization delegation framework
Client Type | Flow | Refresh Tokens |
---|---|---|
Confidential | Authorization Code | X |
Public (Native) | Authorization Code (PKCE) | X |
Public (SPA) | Implicit | -- |
Trusted | RO Password Creds | X |
No Resource Owner | Client Credentials | -- |
GET https://authserver.example.com/authorize
?response_type=token
&client_id=abcdefg
&redirect_uri=https://client.abc.com/callback
&scope=api.read api.write
&state=xyz
HTTP/1.1 302 Found
Location: https://client.abc.com/callback
#access_token=2YotnFZFEjr1zCsicMWpAA
&token_type=bearer
&expires_in=3600
&scope=api.read api.write
&state=xyz
OpenID Connect Core 1.0
OpenID Connect Dynamic Client Registration 1.0
OpenID Connect Discovery 1.0
Id Token (JWT format)
User Info Endpoint
Standard Scopes
Hybrid Grant Flow
OpenID Provider Configuration Information
Base 64 Encoded JSON Formatted Value of...
...Header
...Payload
...Signature
GET / HTTP/1.1
Host: localhost:8080
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1N...
Header
{
typ: "JWT",
alg: "RS256"
}
Payload
{
iss: "https://identity.example.com",
aud: "my-client-id",
exp: 1495782385,
nonce: "N0.46824857243233511495739124749",
iat: 1495739185,
at_hash: "hC1NDSB8WZ9SnjXTid175A",
sub: "mysubject",
auth_time: 1495739185,
email: "test@gmail.com"
}
Scope | Required | Description |
---|---|---|
iss | X | Issuer Identifier |
sub | X | Subject Identifier |
aud | X | Audience(s) of this ID Token |
exp | X | Expiration time |
iat | X | Time at which the JWT was issued |
auth_time | (X) | Time of End-User authentication |
nonce | -- | Associate a client with an ID Token |
GET /userinfo HTTP/1.1
Host: identityserver.example.com
Authorization: Bearer SlAV32hkKG
HTTP/1.1 200 OK
Content-Type: application/json
{
"sub": "248289761001",
"name": "Jane Doe",
"given_name": "Jane",
"family_name": "Doe",
"preferred_username": "j.doe",
"email": "janedoe@example.com",
"picture": "http://example.com/janedoe/me.jpg"
}
https://example.com/.well-known/openid-configuration
{
"authorization_endpoint": "https://idp.example.com/auth",
"grant_types_supported": [
"authorization_code",
"implicit",
"refresh_token"
],
"issuer": "https://idp.example.com",
"jwks_uri": "https://idp.example.com/keys",
"token_endpoint": "https://idp.example.com/token",
"userinfo_endpoint": "https://idp.example.com/userinfo",
...
}
Stuttgart
Torsten Lodderstedt and Daniel Fett
David Waite (PingFederate)
Content-Security Policy
Use a unique redirect URI
Do NOT use refresh tokens
Client Type | Flow | Refresh Tokens |
---|---|---|
Confidential | Authorization Code (PKCE) | X |
Public (Native) | Authorization Code (PKCE) | X |
Public (SPA) | Authorization Code (PKCE) | -- |
Trusted | RO Password Creds | X |
No Resource Owner | Client Credentials | -- |
(“Pixy”)
Mitigates authorization code attacks
Mitigates token leakage in SPAs
GET https://authserver.example.com/authorize
?response_type=code
&client_id=abcdefg
&redirect_uri=https://client.abc.com/callback
&scope=api.read api.write
&state=xyz
&code_challenge=xyz...&code_challenge_method=S256
Client-Id=123, Client-Secret=456
POST https://authserver.example.com/token
Content-Type:
application/x-www-form-urlencoded
grant_type=authorization_code&code=ab23bhW56Xb
&redirect_uri=https://client.abc.com/callback
&client_id=123&client_secret=456
&code_verifier=4gth4jn78k_8
“XSS is Game-Over for OAuth 2” (Jim Manico)
Vittorio Bertocci (Auth0)
Required claims: iss, exp, aud, sub, client_id
Consider privacy restrictions for identity claims
Authorization claims according to SCIM Core (RFC7643):
RFC8471: The Token Binding Protocol Version 1.0
RFC8472: (TLS) Extension for Token Binding Protocol Negotiation
RFC8473: Token Binding over HTTP
OAuth 2.0 Mutual TLS Client Authentication and Certificate-Bound Access Tokens
Spring Security 5.2.0 M2 GitHub Issues
Spring Security 5.2.0 M3 GitHub Issues
Spring Security 5.2.0 RC1 GitHub Issues
Opaque Tokens
class ResSrvConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http)
throws Exception {
http.oauth2ResourceServer()
.opaqueToken()
.introspectionUri(this.introspectionUri)
.introspectionClientCredentials(
this.clientId, this.clientSecret);
}
}
https://github.com/spring-projects/spring-security/issues/5200
class ResSrvConfig extends WebSecurityConfigurerAdapter {
@Override protected void configure(HttpSecurity http) {
http.oauth2ResourceServer()
.authenticationManagerResolver(
multitenantAuthenticationManager());
}
@Bean AuthenticationManagerResolver<HttpServletRequest>
multiTenantAuthMgr() {...}
AuthenticationManager jwt() {...}
AuthenticationManager opaque() {...}
}
https://github.com/spring-projects/spring-security/issues/5351
class ResSrvConfig extends WebSecurityConfigurerAdapter {
@Value("${spring.security.oauth2.resourceserver.
jwt.key-value}") RSAPublicKey key;
@Override protected void configure(HttpSecurity http) {
http.oauth2ResourceServer().jwt().decoder(jwtDecoder());
}
@Bean JwtDecoder jwtDecoder() throws Exception {
return NimbusJwtDecoder.
withPublicKey(this.key).build();
}
}
https://github.com/spring-projects/spring-security/issues/5465
public class OAuth2ResourceServerTest {
@Test
public void testRequestPostProcessor() {
mockMvc.perform(get("/message")
.with(mockAccessToken().scope("message:read")))
.andExpect(status().isOk())
mockMvc.perform(get("/")
.with(jwt().claim(SUB, "the-subject")))
.andExpect(status().isOk())
}
}
https://github.com/spring-projects/spring-security/issues/6634
Support OAuth 2.0 Authorization Server:
All images used are from Pixabay and are published under Creative Commons CC0 license.
All used logos are trademarks of respective companies