Cognito SSO (Single-Sign-On) Demo stack.
The solution consists of 3 parts:
(1) AWS Cognito User Pool with hosted UI and Client Secret
(2) Backend API for authentication/authorization and common CRUD tasks - multiple implementation (NestJs, Flask)
(3) Frontend APP - multiple implementation (React)
/be-1-nestjs
: backend NodeJs / NestJs implementation
/be-2-flask
: backend NodeJs / NestJs implementation
/ui-1-react
: frontend React implementation
/infra
: infrasturcture code (Cognito, CDN, API-s in Lambda) - in separate private repo
the /infra
folder is another linked repository, which contains the infrastructure code of the following elements:
- Cognito User Pool
- NestJs API (backend 1) hosted in AWS Lambda
- Flask API (backend 2) hosted in AWS Lambda
- Multisite CloudFront-S3 distribution for frontend applications
private repository location: Infrastructure Code
- create a Cognito User Pool with hosted UI and Client Secret
- Setup Cognito Client sign-in and sign-out callback endpoints for
http://localhost:3000/signin
andhttp://localhost:3000/signout
- Collect Cognito properties:
Pool ID
,Client ID
,Client Secret
,Hosted UI Domain
,Region
- Launch (any) backend API locally on port 8000 (default). Set environment variables (
.env
or.envrc
file) according to Cognito properties - Launch (any) frontend UI locally on port 3000 (default). Set environment variables (
.env
file) and server URL (eg.http://localhost:8000
)
- the (unauthenticated = w/o tokens) user visits Application website
- the user is redirected to the Cognito Hosted UI in order to sign in (or sign up)
- the user is redirected back to the Application UI with a Cognito Authorization Code in the URL (eg.
http://localhost:3000/signin?code=1234xyz
) - the UI exchanges the Authorization Code with the API for an Access Token and a Refresh Token
- the UI sends the Code for the Server (API)
- the Server exchanges the Authorization Code with Cognito API for the tokens
- the API returns the tokes for the UI
- the user/UI makes normal API requests (eg.
GET /stats
) with the Access Tokens and the Refresh Token sent in the request headers - the Server validates the Access Token JWT with the appropriate Cognito Public Key (JWK)
- in case the Access Token is expired, the Server asks for a new Access Token from Cognito service using the Refresh Token
- the API returns the response (including the newly created Access Token)
- the UI App saves the new Access Token