auth-ms-spring
Secure REST API with OAuth2 and Authorization Service
This project is part of the 'IBM Cloud Native Reference Architecture' suite, available at https://cloudnativereference.dev/
Table of Contents
Introduction
This project demonstrates how to authenticate the API user as well as enable OAuth 2.0 authorization for all OAuth protected APIs in the Storefront reference application.
Interaction with Identity Provider (Auth Microservice)
Interaction with Resource Server API
- When a client wishes to acquire an OAuth token to call a protected API, it calls the OAuth Provider (Authorization microservice) token endpoint with the
username/password
of the user and requests a token with scopeblue
. - Authorization microservice will call the Customer microservice to get the credentials and perform the validation.
- If the
username/password
are valid,HTTP 200
is returned, along with a JWT (signed using a HS256 shared secret) in the JSON response underaccess_token
which contains the auth ID of the user passed in theuser_name
claim. - The client uses the JWT in the
Authorization
header as a bearer token to call other Resource Servers that have OAuth protected API (such as the Orders microservice). - The service implementing the REST API verifies that the JWT is valid and signed using the shared secret, then extracts the
user_name
claim from the JWT to identify the caller. - The JWT is encoded with scope
blue
and the the expiry time inexp
; once the token is generated, there is no additional interaction between the Resource Server and the OAuth server.
Here is an overview of the project's features:
- Leverage
Spring Boot
framework to build a Microservices application. - Uses
Spring Security OAuth
. - Return a signed JWT Bearer token back to caller for identity propagation and authorization
- Uses
Docker
to package application binary and its dependencies.
APIs
Following the OAuth 2.0 specification, the Authorization server exposes both an authorization URI and a token URI.
- GET
/oauth/authorize
- POST
/oauth/token
The Storefront reference application supports the following clients and grant types:
- The Storefront UI is using client ID
bluecomputeweb
and client secretbluecomputewebs3cret
supporting OAuth 2.0 Password grant type.
The Storefront application has scope, blue
.
Pre-requisites:
-
- Installing on MacOS
- Installing on Windows
- Installing on RHEL
- Installing on Ubuntu For more details on installation, check this out.
-
Docker Desktop
Implementation Details
We created a new spring boot project using appsody as follows.
appsody repo add kabanero https://github.com/kabanero-io/kabanero-stack-hub/releases/download/0.6.5/kabanero-stack-hub-index.yaml
appsody init kabanero/java-spring-boot2
And then we defined the necessary code for the application on top on this template.
Running the application on Docker
Get the Auth application
- Clone auth repository:
git clone https://github.com/ibm-garage-ref-storefront/auth-ms-spring.git
cd auth-ms-spring
Run the Auth application
- Before running the application, make sure you grab the
HS256
shared secret.
To make things easier for you, we pasted below the 2048-bit secret here.
E6526VJkKYhyTFRFMC0pTECpHcZ7TGcq8pKsVVgz9KtESVpheEO284qKzfzg8HpWNBPeHOxNGlyudUHi6i8tFQJXC8PiI48RUpMh23vPDLGD35pCM0417gf58z5xlmRNii56fwRCmIhhV7hDsm3KO2jRv4EBVz7HrYbzFeqI45CaStkMYNipzSm2duuer7zRdMjEKIdqsby0JfpQpykHmC5L6hxkX0BT7XWqztTr6xHCwqst26O0g8r7bXSYjp4a
- To run the auth application, use the below command.
appsody run --docker-options "-e HS256_KEY=<Paste HS256 key here>"
- If it is successfully running, you will see something like below.
[Container] 2020-05-05 07:18:23.995 INFO 178 --- [ restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
[Container] 2020-05-05 07:18:24.055 INFO 178 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
[Container] 2020-05-05 07:18:24.108 INFO 178 --- [ restartedMain] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page: class path resource [public/index.html]
[Container] 2020-05-05 07:18:24.634 INFO 178 --- [ restartedMain] d.s.w.p.DocumentationPluginsBootstrapper : Context refreshed
[Container] 2020-05-05 07:18:24.680 INFO 178 --- [ restartedMain] d.s.w.p.DocumentationPluginsBootstrapper : Found 1 custom documentation plugin(s)
[Container] 2020-05-05 07:18:24.751 INFO 178 --- [ restartedMain] s.d.s.w.s.ApiListingReferenceScanner : Scanning for api listing references
[Container] 2020-05-05 07:18:24.926 INFO 178 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
[Container] 2020-05-05 07:18:24.934 INFO 178 --- [ restartedMain] application.Main : Started Main in 10.296 seconds (JVM running for 12.632)
- You can also verify it as follows.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cc1cc3d65ff7 kabanero/java-spring-boot2:0.3 "/.appsody/appsody-c…" 2 minutes ago Up 2 minutes 0.0.0.0:5005->5005/tcp, 0.0.0.0:8080->8080/tcp, 0.0.0.0:8443->8443/tcp, 0.0.0.0:35729->35729/tcp auth-ms-spring
Validating the application
Now, you can validate the application as follows.
curl -i \
-X POST \
-u bluecomputeweb:bluecomputewebs3cret \
http://localhost:8080/oauth/token?grant_type=password\&username=user\&password=password\&scope=blue
If it is successful, you will see something like below.
$ curl -i -X POST -u bluecomputeweb:bluecomputewebs3cret http://localhost:8080/oauth/token?grant_type=password\&username=user\&password=password\&scope=blue
HTTP/1.1 200
Cache-Control: no-store
Pragma: no-cache
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 05 May 2020 07:23:15 GMT
{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODg3MDY1OTUsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiMTBmMmExNGMtOWZmNi00OWI5LWE4NzUtNGVjYzAwNjZkNmY0IiwiY2xpZW50X2lkIjoiYmx1ZWNvbXB1dGV3ZWIiLCJzY29wZSI6WyJibHVlIl19.2vzcyYbm6lYUv0iNl9B15uCBngIbcIsGs2ulC98sAds","token_type":"bearer","refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJ1c2VyIiwic2NvcGUiOlsiYmx1ZSJdLCJhdGkiOiIxMGYyYTE0Yy05ZmY2LTQ5YjktYTg3NS00ZWNjMDA2NmQ2ZjQiLCJleHAiOjE1OTEyNTUzOTUsImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiJdLCJqdGkiOiI0MmMyZjFhZS05NTAyLTQ3M2ItOTAwMy1iODc5NjE0MDFlMGMiLCJjbGllbnRfaWQiOiJibHVlY29tcHV0ZXdlYiJ9.P6eOlzoBk8-d0KKK_7725U0wICosO1G0SYPv8r62-uM","expires_in":43199,"scope":"blue","jti":"10f2a14c-9ff6-49b9-a875-4ecc0066d6f4"}
Originally, in the storefront application, this microservice will talk to customer microservice and validate the credentials. To make it easy for local validation, we enabled a test user which can be used to verify the functionality of this application.
- Also you can access the swagger ui at http://localhost:8080/swagger-ui.html
- We also enabled sonarqube as part of the application.
To run the sonarqube as a docker container, run the below command.
docker run -d --name sonarqube -p 9000:9000 sonarqube
To test the application, run the below command.
./mvnw sonar:sonar -Dsonar.login=admin -Dsonar.password=admin
Now, access http://localhost:9000/
, login using the credentials admin/admin
, and then you will see something like below.
- We included contract testing as part of our application too.
To run Pact as a docker container, run the below command.
cd pact_docker/
docker-compose up -d
To publish the pacts to pacts broker, run the below command.
./mvnw clean install pact:publish -Dpact.broker.url=http://localhost:8500 -Ppact-consumer
To verify the results, run the below command.
./mvnw test -Dpact.verifier.publishResults='true' -Dpactbroker.host=localhost -Dpactbroker.port=8500 -Ppact-producer
Now you can access the pact broker to see if the tests are successful at http://localhost:8500/.
Exiting the application
To exit the application, just press Ctrl+C
.
It shows you something like below.
^CRunning command: docker stop auth-ms-spring
[Container] 2020-05-05 07:31:39.015 INFO 178 --- [ Thread-16] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
[Container] [INFO] ------------------------------------------------------------------------
[Container] [INFO] BUILD SUCCESS
[Container] [INFO] ------------------------------------------------------------------------
[Container] [INFO] Total time: 13:47 min
[Container] [INFO] Finished at: 2020-05-05T07:31:39Z
[Container] [INFO] ------------------------------------------------------------------------
Closing down development environment.
Conclusion
You have successfully deployed and tested the Auth Microservice in local Docker Containers using Appsody.
To see the Auth application working in a more complex microservices use case, checkout our Microservice Reference Architecture Application here.