I am a beginner in Spring outh2 security. I was trying to secure my spring boot rest api's and run them in postman ,
But I always get the "Bearer error="invalid_token", error_description="An error occurred while attempting to decode the Jwt: Signed JWT rejected: Invalid signature", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"" error.
Note:- I am using Azure AD as an authorization server.
Steps followed .
Implemented the below code in STS and ran the application.
Created a access token using the postman "Get New Access Token" using Client Credentials Auth type.
Use that access token and call my spring boot api using Get request.
Note: - When I copy my postman generated token in jwt.io I get a Invalid Signature at the bottom ..but I am able to read the header /payload.
But when I switch the algorithm to HS256 , I don't get an Invalid signature any more.
screenshot of postman
Below is my basic code.
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>resourceserver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>resourceserver</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
My application.properties
server.port=8090
logging.level.org.springframework.security=DEBUG
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://sts.windows.net/tenenentid
Tried using this url as well , but no luck.
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://login.microsoftonline.com/tenentid
Basic Rest api.
#GetMapping("/validateApi")
public String validateApi() {
System.out.println("validateApi");
return "invalid";
}
Not sure if I am missing on any other additional steps. I have not customized any security config as such. So I am assuming it just uses the default configs.
Any help will be appreciated .
Thanks!!
I tried to reproduce the same in my environment and got the results like below:
I generated the access token using below parameters:
https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
client_id:ClientID
client_secret:ClientSecret
scope:https://graph.microsoft.com/.default
grant_type:client_credentials
When I decoded the token, I got the same error as below:
Note that: The token generated for Graph doesn't require validation and it will not verify signature in the code.
Alternatively, to resolve the error you can Expose an API in the Portal like below:
I generated the access token with the scope as api://ClientIDofApp/.default :
The signature got verified successfully like below:
Related
Using a fresh Spring Initialzr with Java17 and Spring Boot 3.0.0, and an extra addition to the pom.xml for Springfox Swagger 3, I can't for the life of me get Swagger pages to work. Instead, I get the whitelabel error page with 404.
Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The standard Swagger URLs as defined in this Github Issues page aren't working for the above pom.xml project.
I had given up and went to use Spring Boot 2.7 after posting the question. But, after seeing Dmitriy's answer though, I checked Springdoc one last time and found that Springdoc v2 does support Spring Boot 3.
Essentially, one has to place the following in their pom:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.0.0</version>
</dependency>
Then one can access the Swagger page using the following URL: http://localhost:8080/swagger-ui.html (Don't forget to add context path if you need it). For some reason, when opening, it redirects to http://localhost:8080/swagger-ui/index.html although going for that initially returned 404...
in addition to adding springdoc-openapi-starter-webmvc-ui (v2.0.2 for me) as indicated in the accepted answer, I also needed to remove org.springdoc:springdoc-openapi-ui:1.6.13 .
It was there because I had tried it before. If present, there's still a non Jakarta reference that Spring tries to resolve (and fails to do so).
I also needed to add this dependency, otherwise I would have a nasty message at startup (version is resolved by Spring Boot BOM) :
implementation group: 'org.hibernate.validator', name: 'hibernate-validator'
Lastest
springfox-boot-starter version 3.0.0
and
springdoc-openapi-ui 1.6.13
seems not to support spring-boot 3.
We need to wait until the new version adopts jakarta.servlet package
Springdoc is working with Spring boot 3.0.1
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.0.2</version>
</dependency>
Default URL: http://localhost:8080/swagger-ui/index.html
For Gradle you can add this:
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.0'
I agreed with #Ahmed Tawfik because I also faced the same. But today I tried that same approach with the new version of "springdoc-openapi-starter-webmvc-ui" dependency and Spring Boot 3.0.2-SNAPSHOT.
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.0.2</version>
</dependency>
because the previous one "springdoc-openapi-ui" is changed to the above one.
Also, include below the path to the security config for swagger UI.
"/v3/api-docs/**","/swagger-ui/**"
For my project,
#Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http.cors(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.exceptionHandling(exceptionHandlingConfigurer -> exceptionHandlingConfigurer.authenticationEntryPoint(unauthorizedHandler))
.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> {
try {
authorizationManagerRequestMatcherRegistry
.requestMatchers(HttpMethod.POST, POST_AUTH_WHITELIST).permitAll()
.requestMatchers(HttpMethod.GET, GET_AUTH_WHITELIST).permitAll()
.requestMatchers("/v3/api-docs/**", "/swagger-ui/**").permitAll()
.anyRequest()
.authenticated()
.and()
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
} catch (Exception e) {
throw new ResourceNotFoundException(e.getMessage());
}
}
)
.formLogin(AbstractHttpConfigurer::disable)
.httpBasic(AbstractHttpConfigurer::disable).addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authenticationProvider(daoAuthenticationProvider()).build();
}
The swagger UI link will be:
http://server:port/context-path/swagger-ui.html
Please adjust the server, port, and context-path regarding your personal changes.
All the above steps are working fine with my project. I don't need extra configuration.
Also, you can add the custom path (Optional):
springdoc.swagger-ui.path=/swagger-ui.html
Here is the Official Documentation of OpenApi 3 and Spring Boot : https://springdoc.org/v2/#features
In the above documentation, you can explore additional configurations and other things also.
Happy Learning! ✌️
Use Open API instead swagger for Spring v3.0. Follow this document Open API Docs
Following dependencies working fine to me.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample.app</groupId>
<artifactId>hello-world</artifactId>
<version>1.0.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
</project>
I got a good and simple SSO sample project from here
Currently the sample works as below.
Start app1, app2, sso-server.
Load http://localhost:8082/app1 It will redirect to login page of
http://localhost:8080/sso-server
username: user, password: password
On successful login, it will redirect back to
http://localhost:8082/app1 The page will show "Welcome to app1, user"
Now on loading http://localhost:8083/app2 The page will show "Welcome
to app2, user" since we have already logged in.
Now my issue is the sample uses spring-boot-starter-parent version 1.5.9.RELEASE
The sample uses spring-cloud dependency also. I read like spring-cloud will not support spring-boot-starter-parent version 2 or above.
So I tried to remove spring cloud dependency from app1 and I could start the application after a tough try. My new pom is as below.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.shekhargulati</groupId>
<artifactId>app1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>app1</name>
<description>App1</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
</dependencies>
Now on loading app1, it will show sso login window. But after successfull login, it will throw 404 error.
And if I do the same changes in sso-server application, the authorization will not work. Authorization API wil lthrow 404.
Please help me to fix this.
My need is, make this application work as earlier with spring boot starter parent version 2+.
Here is the link for the code in github which is forked from the link which is provided in the above question which is providing all the feature you have expected using Spring-Boot 2.X version.
In the above code I have moved your code from Spring boot version 1.5.9.RELEASE to 2.1.3.RELEASE and Spring Cloud version from Edgware.SR1 to Finchley.SR1
I'm new to spring-cloud, so i'm using a video tutorial, so to read exposed endpoints i tried to open http://localhost:8000/actuator/mappings but it didn't work for me but the /health url gave me the following result:
Here's the written code in the client side:
#RefreshScope
#RestController
class MessageRestController {
#Value("${message}")
private String message;
#RequestMapping("/message")
String getMessage() {
return this.message;
}
}
pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.spring.cloud.reservation</groupId>
<artifactId>reservation-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>reservation-service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Here's the client project structure:
bootstrap.properties:
spring.application.name=reservation-service
spring.cloud.config.uri=http://localhost:8888
When executing the Post on the /refresh gives me : Error Not Found
curl -d {} http://localhost:8000/actuator/refresh
spring-boot-actuator jar version = 2.1.3
Default management.endpoints.web.exposure.include, info, health
As actuator/health and actuator/info are provided by default you will get the information
management.endpoints.web.exposure.include = * //will allow all endpoints
to be exposed
management.endpoints.web.exposure.include=health,info # Endpoint IDs that should be included or '*' for all.
management.endpoints.web.exposure.exclude= # Endpoint IDs that should be excluded or '*' for all.
management.endpoints.web.base-path=/actuator # Base path for Web endpoints. Relative to server.servlet.context-path or management.server.servlet.context-path if management.server.port is configured.
management.endpoints.web.path-mapping= # Mapping between endpoint IDs and the path that should expose them.
Securing Endpoint
management.endpoint.health.roles= # Roles used to determine whether or not a user is authorized to be shown details. When empty, all authenticated users are authorized. //for health
management.endpoint.health.show-details=always,never # When to show full health details.
Enable/Disable endpoints
management.endpoint.(endpointName).enabled=true # Whether to enable the health endpoint.
e.g. management.endpoint.health.enabled=true
Spring boot 2.x :: only health and info is exposed by default, In order to expose other actuator endpoint either mention the endpoint name or add following line to expose all endpoints.
management.endpoints.web.exposure.include: '*'
Starting from Spring boot 2.x, all actuator endpoints are disabled except for few non sensitive endpoints like /health and /info by default.
You can enable them using property management.endpoints.web.exposure.include=*
Please refer here for more details.
you have to do post, e.g
curl -X POST xxx.yyy.zzz:8080/actuator/refresh
We have a Spring Boot application with Spring Security enabled. Whenever we try to hit /actuator/health we get the
Whitelabel Error Page -There was an unexpected error (type=Not Found, status=404)
We have the following in application.properties
management.endpoints.web.exposure.include=health,info
management.security.enabled=false
management.security.roles=AMDIN
and in pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Followed this link.
Is there any other role or something which we need to enable ?
Updated: Attached pom.xml and application.property and some more error / warning msgs.
Hi I am very new to Spring Boot and just taking some classes on Udemy for it.
While following through a class, I create a starter project via spring.io and added actuator and Hal browser dependencies including Dev tools.
Just ran my app and tried to go to localhost:8080/application & /browser as well but I get 404.
What am I doing wrong?
I wrote a simple bean which returns a hard coded value and then print that, I changed the value to test Dev tools and it didn’t restart the resource , I had to kill and restart the app to reflect the new changes ..
How can I check what the issue ?
I can provide console grab if needed.
Please help.
Update: I don't know the significance of the following so putting it in here.
in the XML editor hal is red underlined with the following msg on hover:
The managed version is 3.0.5.RELEASE The artifact is managed in org.springframework.data:spring-data-releasetrain:Kay-SR5
in the XML editor devtools is red underlined with the following msg on hover:
The managed version is 2.0.0.RELEASE The artifact is managed in org.springframework.boot:spring-boot-dependencies:2.0.0.RELEASE
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.myoxigen.training.springboot</groupId>
<artifactId>library</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>library</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties file:
logging.level.org.springframework = DEBUG
management.security.enabled=false
Note: This answer is based on Spring Boot 2 (paths and properties have changed from version 1).
Your pom.xml looks fine to me. To get the "HAL Browser" to work with actuator you should have starters: web, actuator, and Rest Repositories HAL Browser. I recommend Spring Initializr as a nice way to construct an initial valid project structure.
The default path for the actuator is /actuator. Health, for example, is at /actuator/health.
To view the actuator endpoints in the HAL Browser, go to /browser/index.html#/actuator.
You can change the actuator path in application.properties by setting the following.
management.endpoints.web.base-path=/actuator
To run your server, use the following console command:
./mvnw clean spring-boot:run
If you have DevTools in your project, then changes to files in your classpath will restart the server. See my further comments on how to take advantage of DevTools here.
Here's the relevant documentation on a single page for easy searching:
https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/reference/htmlsingle
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle
Add this Dependency:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId>
<version>3.3.5.RELEASE</version>
</dependency>`enter code here`
And then go to link:
http://localhost:8080/browser/index.html#
Spring Boot 2.2 apps should use spring-data-rest-hal-explorer rather than spring-data-rest-hal-browser
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-hal-explorer</artifactId>
</dependency>
For enabling actuator, add this into the property file (application.properties)
management.endpoints.web.exposure.include=*
Restart the Spring boot application and access the actuator endpoints using:
http://localhost:8080/actuator/
the health of the application can also be monitored using:
http://localhost:8080/actuator/health
dependency required:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Ain't you were studying a course by "in28minutes"? =) Anyway when I studied on a Spring Boot for Beginners in 10 Steps course, I faced the same issue with accessing http://localhost:8080/application.
For http://localhost:8080/browser I got a plain json:
{"cause":null,"message":"Fragment must not be empty"}
In pom.xml I had the same dependencies as you outlined in question.
Some googling brought me to this article. In section named "II. Hal Browser" you can see a screenshot, where in browser a link is http://localhost:8080/browser/index.html#. If use this link, then Hal Browser should magically appear.
So /index.html# was the only puzzle piece you missed.
Note: above approach worked with Spring Boot version 2.1.7
EDIT: despite the fact that Hal Browser itself works with above approach, it still doesn't show actuator endpoints. And DevTools also ain't working for me.