Sign inSign up

cygni/oauth2-authorization-server

By cygni

•Updated over 6 years ago

Image
0

227

cygni/oauth2-authorization-server repository overview

⁠Authorization server

This is an Authorization Server to be used for educational purpose only, e.g. it contains hardcoded user accounts etc.

⁠Run

Using docker

$ docker run -p 127.0.0.1:8080:8080 --env SECURITY_OAUTH2_REDIRECTURIS=http://frontend.local/oauthcallback --env SECURITY_JWT_SIGNINGKEY=MRzRBGrU2xtK29dcSLRLUmbwXDVxHmPT cygni/oauth2-authorization-server 

Using docker-compose

version: '3.7'

services:
  authorization-server:
    image: cygni/oauth2-authorization-server
    container_name: authorization-server
    environment:
      - SECURITY_OAUTH2_REDIRECTURIS=http://frontend.local/oauthcallback
      - SECURITY_JWT_SIGNINGKEY=MRzRBGrU2xtK29dcSLRLUmbwXDVxHmPT
    ports:
      - '8080:8080'

⁠Security

The Authorization server support OAuth2 with Authorization Code Grant⁠ to obtain JWT access tokens. This is the recommended OAuth2 grant flow for web and mobile apps.

OAuth2 grant flows Implicit flow and Password grant are intentionally not supported as they are considered legacy⁠ and should not be your first choice.

⁠Users

Users and roles that are registered are the following:

UsernamePasswordRole
[email protected]⁠9J5YsK3FYjBBADMIN
[email protected]⁠ARvVxfCHSpFcUSER
[email protected]⁠WXTp2CMK9BZQUSER
⁠Registered clients

One single client is registered:

Client IDSecret
NQqkCbse2rndFKcNZjyn9dbKeANtTDd3cU
⁠Access the REST API

The following sections explain how you generate access_token for a user to be able to access the REST API resources.

⁠1 - Generate an access token
⁠1.1 Browse to the following URI with Client ID = NQqkCbse2r
http://authorization.local/oauth/authorize?response_type=code&client_id=NQqkCbse2r&redirect_uri=http://frontend.local/oauthcallback

You are prompted with a form to enter credentials username and password.

Response: You get redirected (301) to http://frontend.local/oauthcallback?code=EEP9ew. See the code URL param? Thats to be used to fetch the access token.

HINT: If you want to be redirected to another URI e.g. http://frontend.local/oauthcallback⁠ change the value of query param redirect_uri accordingly. Valid values can be configured using for example docker-compose:

authorization-server:
    image: cygni/oauth2-authorization-server
    container_name: authorization-server
    environment:
      - SECURITY_OAUTH2_REDIRECTURIS=http://frontend.local/oauthcallback
      - SECURITY_JWT_SIGNINGKEY=MRzRBGrU2xtK29dcSLRLUmbwXDVxHmPT
⁠1.2 For this example use curl to fetch the token:

Using Client ID = NQqkCbse2r, Secret = ndFKcNZjyn9dbKeANtTDd3cU and Authorization Code = EEP9ew

$ curl --request POST -i --insecure http://authorization.local/oauth/token -H "Authorization: Basic $(echo -n NQqkCbse2r:ndFKcNZjyn9dbKeANtTDd3cU | base64)" -d code=EEP9ew -d grant_type=authorization_code -d redirect_uri=http://frontend.local/oauthcallback

Response:

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
Transfer-Encoding: chunked
Date: Mon, 23 Dec 2019 16:05:05 GMT

{
  "access_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJiYWdhcm4ub2xzc29uQGN5Z25pLnNlIiwic2NvcGUiOlsiYW55Il0sImxhc3RfbmFtZSI6Ik9sc3NvbiIsImV4cCI6MTU4MDYwMTU2OSwiZmlyc3RfbmFtZSI6IkJhZ2FybiIsImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiJdLCJqdGkiOiJjZGRiYjI5MS0xZGQ0LTQyZTEtYmJmMy1hYmEwYWY5ZmE5MTQiLCJjbGllbnRfaWQiOiJOUXFrQ2JzZTJyIn0.rGpDwu-tx10SLKfa3U3NVYiMbgggwf2snd4Vhc2exsg",
  "token_type" : "bearer",
  "refresh_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJiYWdhcm4ub2xzc29uQGN5Z25pLnNlIiwic2NvcGUiOlsiYW55Il0sImF0aSI6ImNkZGJiMjkxLTFkZDQtNDJlMS1iYmYzLWFiYTBhZjlmYTkxNCIsImxhc3RfbmFtZSI6Ik9sc3NvbiIsImV4cCI6MTU4MDY4NzA2OSwiZmlyc3RfbmFtZSI6IkJhZ2FybiIsImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiJdLCJqdGkiOiI1YTE4Nzc5OS1hMjM0LTRiZDAtYWFhNS05ZGJjYzgzYzQ5MTYiLCJjbGllbnRfaWQiOiJOUXFrQ2JzZTJyIn0.WGu_VtGi1FR_CURYwgAZ9bQPLhM8PBqs47yjXxQ-YX4",
  "expires_in" : 899,
  "scope" : "any",
  "first_name" : "Bagarn",
  "last_name" : "Olsson",
  "jti" : "cddbb291-1dd4-42e1-bbf3-aba0af9fa914"
}
⁠Validity of tokens

For the PoC the access_token is valid for 15 minutes. The refresh_token is valid for 24 hours. See details how to refresh the access_token further down in this README.

⁠Decode the access token

The access token is a Json Web Token (JWT). Decoded⁠ the above access_token contains the following information:

{
  "user_name": "[email protected]",
  "scope": [
    "any"
  ],
  "last_name": "Olsson",
  "exp": 1579871135,
  "first_name": "Bagarn",
  "authorities": [
    "ROLE_USER"
  ],
  "jti": "8bfc4b2c-b09f-41b7-b47d-73938af8d492",
  "client_id": "NQqkCbse2r"
}
⁠2 - Use the token to access resources at the backend REST API
$ curl --request GET -i --insecure https://resource.local/api -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJiYWdhcm4iLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwibGFzdF9uYW1lIjoiT2xzc29uIiwiZXhwIjoxNTc5ODcxMTM1LCJmaXJzdF9uYW1lIjoiQmFnYXJuIiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9TVVBFUlVTRVIiXSwianRpIjoiOGJmYzRiMmMtYjA5Zi00MWI3LWI0N2QtNzM5MzhhZjhkNDkyIiwiZW1haWwiOiJiYWdhcm4ub2xzc29uQGN5Z25pLnNlIiwiY2xpZW50X2lkIjoiYktVenRCVWl5MyJ9.3zBnuBSxlJCG7JrhVB8Lf5-h3PbfXQDZ2w4XkGe21F0"

Response:

HTTP/1.1 200
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json
Transfer-Encoding: chunked
Date: Mon, 23 Dec 2019 10:24:17 GMT
   
{
    ...
    ...
}
⁠3 - Refresh access token
$ curl --request POST -i --insecure http://authorization.local/oauth/token -H "Authorization: Basic $(echo -n NQqkCbse2r:ndFKcNZjyn9dbKeANtTDd3cU | base64)" -d grant_type=refresh_token -d refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJiYWdhcm4iLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwiYXRpIjoiOGJmYzRiMmMtYjA5Zi00MWI3LWI0N2QtNzM5MzhhZjhkNDkyIiwibGFzdF9uYW1lIjoiT2xzc29uIiwiZXhwIjoxNTc5OTUwMzM1LCJmaXJzdF9uYW1lIjoiQmFnYXJuIiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9TVVBFUlVTRVIiXSwianRpIjoiZDkzZTJmOTQtODQzMC00NWJhLThkNGMtNTc4Mjc4NzkxYjAxIiwiZW1haWwiOiJiYWdhcm4ub2xzc29uQGN5Z25pLnNlIiwiY2xpZW50X2lkIjoiYktVenRCVWl5MyJ9.IhbDbs29nfxVGfPMqsC6B7Pg6bwsGWdBrMM9CgnKkhk

Response:

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
Transfer-Encoding: chunked
Date: Mon, 23 Dec 2019 18:49:41 GMT

{
  "access_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJiYWdhcm4iLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwibGFzdF9uYW1lIjoiT2xzc29uIiwiZXhwIjoxNTc5ODc2Mzk3LCJmaXJzdF9uYW1lIjoiQmFnYXJuIiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9TVVBFUlVTRVIiXSwianRpIjoiNTA1NTgxOGItODJmYi00YWUyLWI5ZjMtNWI1OWZkNDViODM0IiwiZW1haWwiOiJiYWdhcm4ub2xzc29uQGN5Z25pLnNlIiwiY2xpZW50X2lkIjoiYktVenRCVWl5MyJ9.9RJbtGah5cp2ErVAmPKmiKiHN8A6G8vTi3b9n6vp8-g",
  "token_type" : "bearer",
  "refresh_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJiYWdhcm4iLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwiYXRpIjoiNTA1NTgxOGItODJmYi00YWUyLWI5ZjMtNWI1OWZkNDViODM0IiwibGFzdF9uYW1lIjoiT2xzc29uIiwiZXhwIjoxNTc5OTU1NTk3LCJmaXJzdF9uYW1lIjoiQmFnYXJuIiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9TVVBFUlVTRVIiXSwianRpIjoiZWI4NzFjNzMtODkzYy00OTFkLTg2OWYtY2QzMzFkMzhhYjA3IiwiZW1haWwiOiJiYWdhcm4ub2xzc29uQGN5Z25pLnNlIiwiY2xpZW50X2lkIjoiYktVenRCVWl5MyJ9.CTngJDnpNUZ4i22TIVd_sxVgKCN9PwfZBHJgJqxZN0A",
  "expires_in" : 7199,
  "scope" : "any",
  "first_name" : "Bagarn",
  "last_name" : "Olsson",
  "jti" : "5055818b-82fb-4ae2-b9f3-5b59fd45b834"
}
⁠4 - Logout

By design a JWT is self contained. Meaning it makes little sense to invalidate an access token. For obvious reasons --> since it is self contained.

For a client to support logout two approaches in combination should be used:

  • Provided by Authorization server - Reasonably short lifetime of JWT access tokens. 15 minutes are chosen by this service,
  • Provided by Client - Delete a JWT from local storage or equivalent when issuing a logout event.

Tag summary

Content type

Image

Digest

Size

268 MB

Last updated

over 6 years ago

docker pull cygni/oauth2-authorization-server