Since a long time I wanted to integrate an OpenID Connect provider using Spring Security, The last time I tried, I felt it was very complicated and wrote my own library. Since Spring Security 5 has native support for OAuth2 Client and extended its use for OpenID connect, I wanted to see how easy it is to integrate.
For this example we are going to build a simple app, the redirects to google when we try to access a protected endpoint
Step 1:
Create a spring boot project from https://start.spring.io with following dependencies
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
implementation 'org.jetbrains.kotlin:kotlin-reflect'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
}
Step 2:
Create an endpoint that will show current user's authentication data
@RestController
class HelloController {
@GetMapping("/me")
fun hello(currentUser: OAuth2AuthenticationToken): ResponseEntity<OAuth2AuthenticationToken> {
return ResponseEntity.ok(currentUser)
}
}
Step 3:
Configure OAuth2 Client information in application.yml. In google's developer console configure the app's redirect uri as http://localhost:8080/login/oauth2/code/google
# @see https://console.developers.google.com/apis/ to create your client credentials
logging.level.org.springframework: INFO
spring:
security:
oauth2:
client:
registration:
google:
provider: google
client-id: <<your-client-id>>
client-secret: <<your-client-secret>>
client-authentication-method: basic
authorization-grant-type: authorization_code
scope:
- openid
- email
- profile
- https://www.googleapis.com/auth/tasks.readonly
provider:
google:
issuer-uri: https://accounts.google.com
Step 4:
Run the application, goto http://localhost:8080/me , complete the login process and you will see this.
{
"authorities": [
{
"authority": "ROLE_USER",
"attributes": {
"at_hash": "28AV0o6xKM8f3UQlljlGuw",
"sub": "10080000000000000",
"email_verified": true,
"iss": "https://accounts.google.com",
"given_name": "Syamala",
"locale": "en",
"picture": "https://lh6.googleusercontent.com/photo.jpg",
"aud": [
"client-id"
],
"azp": "client-id",
"name": "Syamala Umamaheswaran",
"exp": "2019-03-24T18:27:19Z",
"family_name": "Umamaheswaran",
"iat": "2019-03-24T17:27:19Z",
"email": "xxxx@gmail.com"
},
"idToken": {...},
"userInfo": null
}
],
"details": null,
"authenticated": true,
"principal": {},
"authorizedClientRegistrationId": "google",
"credentials": "",
"name": "10080000000000000"
}
Mind Blown:
As much as it blows my mind that without writing any code for security we are able to integrate with an OpenID Connect provider, I needed to know how this is working so easily. The Devil is in the details, Stay tuned for my next blog post where I explain the behind the scenes and How to access a protected resource and how to refresh tokens automatically.
Complete Source Code @ https://github.com/shyamz-22/oidc-spring-security-5
Top comments (9)
Looking forward for the next article. I had to integrate with a provider that used slightly non-standard definition of OAuth2 for my personal project and it was like extra 400 lines of code just to get a response with user details because once I started poking around Spring Boot autoconfiguration stopped working. Having to write my own security configuration like I know what I'm doing definitely was a learning experience
Thanks for the feedback. Here is the next article, dev.to/shyamala_u/spring-boot--spr....
How to disable displaying login page in spring security 6? I am trying to disable it doing like this:
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable());
return http.authorizeHttpRequests((authorize) -> authorize.anyRequest().permitAll()).build();
}
but it is not working. Could you please help me out?
Hello,
I followed the instructions but I get a
"An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: 401 Unauthorized"
Do you know what could be the problem? I created the credentials in my google account. I don't know if there are additional steps to do there.
Thanks
Hi,
Have you checked if the combination of client-id and client-secret is the right value?
Hi there, great post, but I have a question how to do the same authorization for twitter, as you know twitter is on oAuth1.0a and requires some request token, what I tried is this:
twitter:
clientId: my_twitter_client_id_goes_here
clientSecret: my_twiiter_client_secret_goes_here
redirectUriTemplate: "{baseUrl}/oauth2/callback/{registrationId}"
authorization-grant-type: authorization_code
scope:
- email
- profile
provider:
twitter:
authorizationUri: api.twitter.com/oauth/authorize
tokenUri: api.twitter.com/oauth/access_token
userInfoUri: api.twitter.com/1.1/users/show.json
but I always get the same page from twitter:
Whoa there!
There is no request token for this page. That's the special key we need from applications asking to use your Twitter account. Please go back to the site or application that sent you here and try again; it was probably just a mistake.
any help would be appreciated
p.s. google and facebook are working fine because they are on oAuth2.0
I will have a look and revert, Thank you for the feedback :)
Hi Shyamala,
Simply Superb article,
How to do this using Spring xml configuration.
Thank you for the feedback. I have not worked with XML Config for a long time, I shall check .