Get 401: Invalid Token After install okta-spring-boot-starter - java

Hi I am now using Angluar + Spring Boot to build a web, I am using okta Single-Page App to do authentication. On my frontend, I can login and redirect back, I also add Authorization: Bearer {Token} in the headers when I call backend api.
So the problem is when I installed okta-spring-boot-starter(1.4.0), and I will get the error:
Bearer error="invalid_token", error_description="An error occurred while attempting to decode the Jwt: Invalid token", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"
I was thinking this might because I didn't setup okta configuration.
Then I add the okta properties in application.yml file:
spring:
profiles:
active: "dev"
main:
banner-mode: "off"
okta.oauth2:
client-id: 0oaebbeiaBCbFFtDU4x6
issuer: https://dev-574831.okta.com
audience: https://dev-574831.okta.com
and use WebSecurityConfigurerAdapter by refering to: https://github.com/okta/samples-java-spring/blob/master/resource-server/src/main/java/com/okta/spring/example/ResourceServerExampleApplication.java
import com.okta.spring.boot.oauth.Okta;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
public class OktaOAuth2WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/userinfo").permitAll()
.antMatchers("/health").permitAll()
.anyRequest().authenticated()
.and()
.oauth2ResourceServer().jwt();
http.cors();
Okta.configureResourceServer401ResponseBody(http);
}
}
Still I am getting the same error.
So do I miss something?? or can okta configuration cannot be recognized by my project?

Try this:
okta:
oauth2:
client-id: 0oaebbeiaBCbFFtDU4x6
issuer: https://dev-574831.okta.com/oauth2/default

Related

Spring Boot with Cognito always shows login screen in postman

I am trying to debug a spring boot application secured behind AWS cognito.
I have set up the user pools and app config according to these tutorials:
https://www.baeldung.com/spring-security-oauth-cognito
https://www.czetsuyatech.com/2021/01/aws-generate-cognito-access-token.html
https://betterjavacode.com/programming/example-of-spring-boot-application-authentication-with-aws-cognito
I am only interested in programmatic REST access, not spring mvc.
Demo Controller:
#GetMapping(path = "/hello")
public ResponseEntity<String> hello() {
System.out.println("Hello");
return new ResponseEntity<>("Hello", HttpStatus.OK);
}
application.yml
spring:
servlet:
multipart:
max-file-size: 50MB
max-request-size: 50MB
security:
oauth2:
client:
registration:
cognito:
clientId: xxxxxx
clientSecret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
scope: openid
redirect-uri: http://localhost:8080/login/oauth2/code/cognito
clientName: w3p-app-client
provider:
cognito:
issuerUri: https://cognito-idp.us-east-1.amazonaws.com/us-east-1_zcZ0Enk0d
user-name-attribute: cognito:username
Security Config:
#Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.oauth2Login()
.and()
.logout()
.logoutSuccessUrl("/");
}
}
And this works in a browser localhost:8080/hello. I get the cognito login page where I can sign in with a demo user created in the user pool. After that I get the text "Hello" in my browser as expected.
Now I wanted to setup a postman collection for testing my API:
"Get New Access Token" opens the cognito login where I can successfully sign in and obtain the token. However if I now try to acces my /hello, with inherited auth from the parent, I still get redirected to the cognito login every time, even though the token is sent along.
I have saved the collection and request, I have tried with and without bearer, enabled all options in cognito and whatnot. At this point I am out of ideas. Any hints would be appreciated. For some reason cognito does not redirect to my api as in the browser, but send the login page instead. It seems like any auth setting is completely ignored, same behavior with "no auth" selected.
In your case your service is in the role of a resource server. In the context of OAuth2 a resource server is an application, which endpoints are secured via OAuth tokens.
The basic configuration to make this work would be:
Add the following dependencies in your pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
In your application.yml:
spring:
security:
oauth2:
resourceserver:
jwt:
https://cognito-idp.us-east-1.amazonaws.com/us-east-1_zcZ0Enk0d
Your resource server will use this property to validate the incoming JWT tokens.
This is all you need in order to secure all your endpoints.
If you need to add any custom security configuration here is an example:
#Configuration
#EnableWebSecurity
public class CustomSecurityConfiguration {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(authorize -> authorize
.mvcMatchers("/my-public-endpoint").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
.build();
}
}
You can find further information in the spring-security documentation
Here is also one tutorial
Your problem is in your SecurityConfiguration. You defined everything for anyRequest. You can use antMatchers to define authentication only for some request based on URL-path. Or you can give free access with permitAll to limited URLs by path with antMatchers. Here is an example how antMatchers can be used and how you can deal with all remaining (anyRequest) URL-paths.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/needToken").authenticated()
.anyRequest().permitAll();
}

OAuth2 flow for Gateway + Backend Service

I'm currently building a web-application using Spring-Boot-Web in combinition with OAuth2 using Amazon-Cognito on AWS.
My target setup looks like this:
In "My-Datacenter" I have 2 applications running:
Gateway-Application
Backend-Application
The Gateway-Application is accessible from the internet. It serves the frontend (html, css, js), contains some display logic and maybe some APIs that are accessible for everyone. It is the initiator for the "Authorization Code Grant"-OAuth 2.0 Flow (it redirects the user to Amazon-Cognito if the user isn't yet logged in).
The Backend-Application is only accessible by the Gateway-Application. It is not accessible from the outside. In the Backend-Application I want to retrieve user-details (Name, E-Mail) from Amazon-Cognito.
What I got to work at the moment:
I registered one client for the Gateway-Application in Amazon-Cognito. The Gateway-Application initiates the "Authorization Code Grant"-Flow and can access the user-information from Amazon-Cognito.
I configured the Gateway-Application to pass the OAuth2-Authorization-Details to the Backend-Application with all my HTTP-Requests. The Backend-Application can successfully check whether the user is authenticated or not.
Gateway-Application configuration
application.yml
spring:
security:
oauth2:
client:
registration:
cognito:
client-name: frontend-local
client-id: #######
client-secret: #########
scope: openid,backend/read,backend/write
redirect-uri: http://localhost:8080/login/oauth2/code/cognito
provider:
cognito:
issuer-uri: https://cognito-idp.eu-central-1.amazonaws.com/<my-aws-pool-id>
user-name-attribute: cognito:username
SecurityConfiguration.java
package io.share.frontend.configuration;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.and()
.authorizeRequests().antMatchers("/", "/webjars/**").permitAll().anyRequest().authenticated()
.and()
.oauth2Login()
.and()
.logout().logoutSuccessUrl("/");
}
}
OAuth2WebClientConfiguration.java
package io.share.frontend.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
#Configuration
public class OAuth2WebClientConfiguration {
#Bean
public OAuth2AuthorizedClientManager authorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository) {
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
#Bean
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oauth2Client.setDefaultClientRegistrationId("cognito");
return WebClient.builder()
.apply(oauth2Client.oauth2Configuration())
.build();
}
}
Backend-Application configuration
application.yml
server:
port: 8081
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://cognito-idp.eu-central-1.amazonaws.com/<my-aws-pool-id>
SecurityConfiguration.java
package io.share.backend.configuration;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().hasAuthority("SCOPE_backend/read")
.and()
.oauth2ResourceServer().jwt();
}
}
What I want to get to work
In my Backend-Application, I want to be able to access to User-Information from Amazon-Cognito. Currently, I have the following basic RestController in my Backend-Application:
package io.share.backend.web;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.security.Principal;
#RestController
public class ObjectResource {
#GetMapping("/username")
public String greeting(#AuthenticationPrincipal Principal user) {
return user.getName();// this currently returns some UUID-Like string, I want to be able to access the username and E-Mail here, just like I can in the Gateway
}
}
But I want to be able to access the real Username and E-Mail in the Backend.
My question
Do I have to create a new client in Amazon-Cognito for the backend? Or do I have to configure the same client-id and client-secret for the Gateway and Backend?
Which additional Spring-Configurations do I have to make in my Applications (both Gateway and Backend) to make this work?
I'm using spring-boot 2.3.6.RELEASE
Good question and you are running into the following common OAuth issue with APIs:
Cognito access tokens contain very little user info, which is good practice - they are not customisable and only include a subject claim
Spring wants to create an AuthenticatedPrincipal from just the JWT - but your API also wants additional claims to be added to the AuthenticatedPrincipal
DESIGN PATTERN
There is a design pattern you can use, or borrow ideas from, and my blog post summarises the behaviour. The idea is to define a Claims Principal first, then to populate it with claims from multiple sources at runtime. In your case one source will be the Cognito User Info endpoint.
WORKING CODE
You can run my Sample Spring Boot API, which also uses AWS Cognito, and the key class is the Authorizer. In some setups you may be able to get an API Gateway to do some of this work for you:
How to Run the API
Spring Boot OAuth Integration with Custom Claims
PROs and CONs
This pattern will give you extensible claims but it will also add some complexity to your API, since you need to override the API technology stack's default OAuth behaviour.

okta oauth2 Spring security all protected pages redirect to login

I am trying to implement okta(custom-provider) oauth2 sso feature using spring security in my application. Application successffully prompts for the user login and authorises the user. I have my spring security config given below. The problem here is except the login and few other urls which are given permitAll() , all the protected pages are getting redirected to 'redirect-uri'(which is the login url) configured in the application.yml given below. I cannot understand why this happens i couldnt find any solution given in the okta documentation as well. I dont see any error messages in the log. Its just everytime i get to access the secured or protected page the redirect happens to http://localhost:8080/login which is the redirect-uri but i need the redirect to go to the corresponding page the user selected. Am i missing anything here ?
SecurityConfiguration.java
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests()
.antMatchers("/","/login**","/vendor/**", "https://fonts.googleapis.com/**", "/css/**",
"https://www.thymeleaf.org", "/js/**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login();
}
}
application.yml
security:
oauth2:
client:
registration:
custom-client:
client-id:
client-secret:
scope: ["openid", "profile", "email", "address", "phone", "groups"]
provider: custom-provider
state: xoxoxo
redirect-uri: http://localhost:8080/login
client-authentication-method: basic
authorization-grant-type: authorization_code
filter-order: 3
provider:
custom-provider:
token-uri: https://did.oktapreview.com/oauth2/v1/token
authorization-uri: https://did.oktapreview.com/oauth2/v1/authorize
user-info-uri: https://did.oktapreview.com/oauth2/v1/authorize
user-name-attribute: name
can someone
Yes sure, there is a wrong thing.
redirect-uri: http://localhost:8080/login
redirect-uri should be a link to the callback endpoint of your OAuth2.0 Client
In terms of Spring Security OAuth2.0 framework it should be the following pattern:
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
where "baseUrl" is your URL (http://localhost)
and "registrationId" is registration name, in your case it is "custom-client"
Actually, you can specify, as "redirect-uri" parameter, a pattern without certain registrationId and baseUrl, so that your configuration should be looks like that:
security:
oauth2:
client:
registration:
custom-client:
client-id:
client-secret:
scope: ["openid", "profile", "email", "address", "phone", "groups"]
provider: custom-provider
state: xoxoxo
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
client-authentication-method: basic
authorization-grant-type: authorization_code
filter-order: 3
provider:
custom-provider:
token-uri: https://did.oktapreview.com/oauth2/v1/token
authorization-uri: https://did.oktapreview.com/oauth2/v1/authorize
user-info-uri: https://did.oktapreview.com/oauth2/v1/authorize
user-name-attribute: name
Also, pay attention to your credentials, it should be filled.

Hosted Authorization Server does not redirect to localhost client

So I have followed the guide here to implement a Spring Authorization Server. I have managed to get both a client and server ready for testing. The reason why I need and authorization server is because I need to be able to authenticate multiple microservices that work together.
I have run both the server and client on my machine. The authorization server at localhost:9999 and the client at localhost:8080/client (setting the client app context-path to /client). The authentication for the client works perfectly in this scenario. To make this easy, I decided to host the authorization server on AWS using Elastic Beanstalk. For secrecy, I will use SERVER_URL as the hosted authorization server's URL.
Once the server is hosted, I run the client using the hosted authorization server with the correct token and authorization URLs. Once I go to localhost:8080, I get redirected to SERVER_URL where the homepage displays a link to Google OAuth login. Clicking on that link takes me to google login and I login with my google account. After the google login, it redirects back to SERVER_URL/login?code=the_code&state=the_state. This is is not what I want. After logging into Google, the user should be redirected back to localhost:8080/login?code=the_code&state=the_state.
I have been researching for days but cannot seem to find a solution to this problem. I need to be able to test multiple microservices on localhost with the hosted server.
My authorization server main application class is the default (I haven't added anything). Here is my security configuration:
#Configuration
#EnableWebSecurity
#EnableOAuth2Client
#EnableAuthorizationServer
#Order(200)
public class OAuthSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final String GOOGLE_LOGIN_FILTER = "/login/google";
#Autowired
OAuth2ClientContext oauth2ClientContext;
#Bean
#ConfigurationProperties("google")
public ClientResources google() {
return new ClientResources();
}
private Filter ssoFilter() {
return ssoFilter(google(), GOOGLE_LOGIN_FILTER);
}
private Filter ssoFilter(ClientResources client, String path) {
OAuth2ClientAuthenticationProcessingFilter googleFilter = new OAuth2ClientAuthenticationProcessingFilter(GOOGLE_LOGIN_FILTER);
OAuth2RestTemplate googleTemplate = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
googleFilter.setRestTemplate(googleTemplate);
UserInfoTokenServices tokenServices = new UserInfoTokenServices(client.getResource().getUserInfoUri(), client.getClient().getClientId());
tokenServices.setRestTemplate(googleTemplate);
googleFilter.setTokenServices(tokenServices);
return googleFilter;
}
#Bean
public FilterRegistrationBean<OAuth2ClientContextFilter> oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
FilterRegistrationBean<OAuth2ClientContextFilter> registration = new FilterRegistrationBean<OAuth2ClientContextFilter>();
registration.setFilter(filter);
registration.setOrder(-100);
return registration;
}
/**
* Specify the authorization criteria for request access.
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**")
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/"))
.and()
.logout()
.logoutSuccessUrl("/")
.permitAll()
.and()
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class)
.csrf()
.disable();
}
}
class ClientResources {
#NestedConfigurationProperty
private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();
#NestedConfigurationProperty
private ResourceServerProperties resource = new ResourceServerProperties();
public AuthorizationCodeResourceDetails getClient() {
return client;
}
public ResourceServerProperties getResource() {
return resource;
}
}
Then I have a separate class for protecting the "/me" path:
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/me")
.authorizeRequests()
.anyRequest()
.authenticated();
}
}
And my application.yml for the auth server:
spring:
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
server:
port: ${PORT:9999}
error:
whitelabel:
enabled: false
security:
oauth2:
client:
client-id: google client id
client-secret: google client secret
scope: read,write
auto-approve-scopes: '.*'
google:
client:
clientId: google client id
clientSecret: google client secret
accessTokenUri: https://oauth2.googleapis.com/token
userAuthorizationUri: https://accounts.google.com/o/oauth2/auth
clientAuthenticationScheme: form
scope:
- openid
- profile
- email
resource:
userInfoUri: https://www.googleapis.com/oauth2/v3/userinfo
preferTokenInfo: true
The controller for "/me" path is trivial, so I am not going to include that here. And yes, I am using the same google client id and secret for Google and the server itself (for now).
Now on my client side, the application.yml:
authorization-server-url: SERVER_URL
security:
oauth2:
client:
clientId: google client id
clientSecret: google client secret
accessTokenUri: ${authorization-server-url}/oauth/token
userAuthorizationUri: ${authorization-server-url}/oauth/authorize
resource:
userInfoUri: ${authorization-server-url}/me
And the security configuration on my client side uses #Configurable, #EnableWebSecurity, and #EnableOAuth2SSO. The security configuration prevents access of unauthenticated users, which is why as soon as I go on localhost:8080, it redirects me to the auth server.
The auth server, when used by itself, successfully logs into google. And if the client application at localhost:8080 is configured to authenticate with Google OAuth directly instead of the custom auth server, then it does that successfully. The problem is the proper redirect after the auth server has logged in with Google.
Just to clarify, I am after the flow localhost:8080 -> auth server -> click link which takes you to SERVER_URL/login/google -> Login with Google -> localhost:8080. But what I'm getting is localhost:8080 -> auth server -> click link which takes you to SERVER_URL/login/google -> Login with Google -> SERVER_URL/login?code=the_code&state=the_state.
Thanks in advance.
EDIT:
Here is my gradle configuration:
buildscript {
ext {
springBootVersion = '2.0.5.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'war'
group = this is a secret
version = '0.0.4-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
configurations {
providedRuntime
}
ext {
springCloudVersion = 'Finchley.SR1'
}
dependencies {
implementation('org.springframework.boot:spring-boot-starter-security')
implementation('org.springframework.boot:spring-boot-starter-web')
implementation('org.springframework.cloud:spring-cloud-starter-oauth2')
implementation('javax.servlet:jstl')
implementation('org.apache.tomcat.embed:tomcat-embed-jasper')
providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
testImplementation('org.springframework.boot:spring-boot-starter-test')
testImplementation('org.springframework.security:spring-security-test')
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
EDIT 2:
The error page I get is at the url http://<SERVER_URL>/login?code=xgYiHr&state=Wp1SUW where <SERVER_URL> is the domain name of the authorization server. And I get the following error page:
And the Network traffic for the error page. According to this, http://<SERVER_URL>/oauth/authorize has the correct redirect_uri which is http://localhost:8080/login, but when it comes to redirecting to it the localhost:8080 url gets replaced with <SERVER_URL>:
Funny thing is, I just tried running the client application through http://127.0.0.1:8080 instead of http://localhost:8080 and it works perfectly! Not sure why localhost:8080 gets replaced by the <SERVER_URL>. I'm not sure if this problem is with AWS or Spring.
It seems like I was right in thinking there is something wrong with my AWS setup. I changed the environment in Elastic Beanstalk to use Nginx as the Proxy server, which solved my issue. Now I can test my client using localhost instead of 127.0.0.1.

Spring Boot 2 + OAuth2: Configure Exchange of Auth Code for Token

I've followed this Spring Boot OAuth2 tutorial on configuring an OAuth2 client. Unfortunately, once a "user" authenticates with the Idp (Okta) a redirect with a "code" takes place that results in a redirect loop of: /login -> /authorize... -> /login... -> /login
Firefox has detected that the server is redirecting the request for this address in a way that will never complete.
Does anyone know what is or could be the issue and how to solve it? Details follow.
Okta configuration:
Login redirect URIs: http://localhost:8080/auth/login
Logout redirect URIs:
http://localhost:8080/auth/logout
Login initiated by: App only
Initiate login URI: http://localhost:8080/auth/login
The configuration properties are:
okta:
oauth2:
client:
client-id: clientId
client-secret: clientSecret
scope: openid profile email
client-authentication-scheme: form
access-token-uri: https://mydomain.oktapreview.com/oauth2/myapp/v1/token
user-authorization-uri: https://mydomain.oktapreview.com/oauth2/myapp/v1/authorize
resource:
user-info-uri: https://mydomain.oktapreview.com/oauth2/myapp/v1/userinfo
The filter is:
private Filter filter() {
OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(
"/login");
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(oktaClient(), oauth2ClientContext);
filter.setRestTemplate(restTemplate);
UserInfoTokenServices tokenServices = new UserInfoTokenServices(oktaResource().getUserInfoUri(),
oktaClient().getClientId());
tokenServices.setRestTemplate(restTemplate);
filter.setTokenServices(tokenServices);
return filter;
}
The WebSecurityConfigurerAdapter configure is:
#Configuration
#EnableOAuth2Client
public class WebSecConfig extends WebSecurityConfigurerAdapter {
....
#Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests()
.antMatchers("/", "/login**", "/logout**", "/v2/api-docs", "/configuration/ui",
"/configuration/security", "/swagger-resources/**", "/swagger-ui.html", "/webjars/**")
.permitAll()
.anyRequest().authenticated().and().exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")).and().csrf()
.csrfTokenRepository(
CookieCsrfTokenRepository.withHttpOnlyFalse()).and().addFilterBefore(filter(),
BasicAuthenticationFilter.class);
}
....
}
Update:
Solution was to change LoginUrlAuthenticationEntryPoint("/login") to LoginUrlAuthenticationEntryPoint("/") and re-create the authorization server.
You should use the default authorization server, or one you created. If you use the default, it should look something like:
https://mydomain.oktapreview.com/oauth2/default

Categories