spring-projects / spring-projects/spring-security
Support prompt in OIDC flows
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 9.6k
- Forks
- 6.3k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 52
Description
Summary
Some workflows in OpenID Connect are dependent on being able to use prompt=none to asynchronously refresh the session in the background. In particular, the draft specs for session management depend on the ability to use prompt=none via requests in a hidden iframe (see section 4.1). This is analogous to using isPassive in a SAML2 AuthnRequest.
In order to do that in a web application using spring-security, the OAuth2AuthorizationRequestResolver in use needs to be able to send the prompt=none flag when redirecting a user to an upstream identity provider when non-interactivity is requested by a user. This would also imply that a mechanism would be needed by which clients can request non-interactive session refreshes (which could theoretically share behavior between OIDC & other backing systems such as SAML)
Currently, there is no support for this in DefaultOAuth2AuthorizationRequestResolver, which is used by default when configuring an OpenID Connect login flow. See also some discussion of this in #6742
Configuration
in the WebSecurityConfigurerAdapter:
// this actually comes from Springboot properties:
String loginPage = "/oauth2/authorization/wso2";
// ...
http
.addFilterAfter(ajaxTimeoutRedirectFilter, ExceptionTranslationFilter.class) // return 401 when attampting unauthenticated AJAX
.logout().logoutSuccessHandler(oidcLogoutRedirectHandler()).permitAll() // should go away with support in spring-security 5.2
.and()
.authorizeRequests()
.antMatchers("/censoredPage1.html").hasRole("role1")
.antMatchers("/censoredPage2.html").hasRole("role2")
.anyRequest().authenticated() // functional controllers responsible for their own authorization
.and()
.oauth2Login()
.loginPage(loginPage) // only one identity provider should be configured - just go directly there
.userInfoEndpoint().oidcUserService(userService) // add internal numeric user ID which maps to incoming subject
.and().and()
.sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry) // allows session-killing to refresh authorization grants when they change
.expiredSessionStrategy(new CallFailureSessionInformationExpiredStrategy(loginPage)); // on expired sessions: redirect synchronous requests, 401 async requests
in Spring-boot properties:
# NOTE: you need these two, but they're given by the OIDC provider (WSO2 Identity Server)
# spring.security.oauth2.client.registration.wso2.client-id =
# spring.security.oauth2.client.registration.wso2.client-secret =
# spring.security.oauth2.client.registration.wso2.client-name =
spring.security.oauth2.client.registration.wso2.provider=wso2
# Note well: The scope list MUST be separated by commas. There are multiple uses for this and some will work
# if you use spaces but others will fail in significant ways (like bypassing OIDC support and using OAuth2).
spring.security.oauth2.client.registration.wso2.scope=openid,email,phone
spring.security.oauth2.client.registration.wso2.redirect-uri-template=${my_url}/login/oauth2/code/wso2
spring.security.oauth2.client.registration.wso2.client-authentication-method=basic
spring.security.oauth2.client.registration.wso2.authorization-grant-type=authorization_code
spring.security.oauth2.client.provider.wso2.authorization-uri=${wso2.oauth2-root}/authorize
spring.security.oauth2.client.provider.wso2.token-uri=${wso2.issuer}
spring.security.oauth2.client.provider.wso2.user-info-uri=${wso2.oauth2-root}/userinfo
spring.security.oauth2.client.provider.wso2.jwk-set-uri=${wso2.oauth2-root}/jwks
spring.security.oauth2.client.provider.wso2.user-name-attribute=sub
server.port = 8443
my_hostname = https://localhost
my_url = ${my_hostname}:${server.port}
wso2.baseUrl = ${my_hostname}:9443
wso2.oauth2-root = ${wso2.baseUrl}/oauth2
wso2.issuer = ${wso2.oauth2-root}/token
Version
5.1.5 (via spring-boot 2.1.4)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with DefaultOAuth2AuthorizationRequestResolver and the discussion referenced in #6742. Determine how clients should request non-interactive OIDC session refreshes and how that request reaches an upstream identity provider. Done means supporting prompt=none for the described hidden-iframe flow without requiring a custom resolver.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- authentication, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100