Simple NestJS RESTful API CRUD fullstack application using Pokemon Gen 1 dataset and utilizing Kong API Gateway and Keycloak with OpenID Connect/OAuth 2.0 demonstrating:
- Application, MongoDB containerization in Docker and database seeding.
- Volume mapping and persisting database data in db container.
- Environment variable configuration and validation.
- URI versioning, Swagger configuration and documentation.
- REST API calls invoking CRUD operations.
- Validating API request BODY and PARAMS based on DTO's using pipes.
- Annotating schemas, dto's and controllers.
- Creation and usage of Data Transfer Objects and Mongoose Schemas.
- Mitigating common attack vectors by setting HTTP response headers using Helmet.
- Rate limiting to prevent-brute force attacks, by limiting application to 10 requests within 60 second time period as an example.
- Implementation and usage of open source API gateway proxying traffic to services within Docker network. Kong API Gateway
- Secure the client (Swagger UI), preventing unauthenticated requests to backend API's using Kong, Keycloak and OpenID Connect (OIDC).
NOTE: This personal project was rushed as a learning/upskilling exercise and is not production quality.
- Authorization/Role-based access control to determine what users can do.
- Microservices Architecture
- Docker
- Node v18+ (if running pokemon service locally)
Use docker compose to setup the docker environment for the application and other services. The docker compose file contains all the configurations and commands required to build the application, database and seed the dataset into the db.
# Builds, (re)creates, starts, and attaches to containers for a service in detached mode. Ommit -d if you don't want to run in detached mode.
$ docker compose up -d
If you want to run the application locally in development/watch mode, follow these steps:
# If the containers are already running use this command to stop and remove containers, networks.
$ docker compose down
# Start the mongo database container, it is a prerequisites as the application connects to the database on start up.
$ docker compose up mongo mongo-seed -d
# Start application
# development
$ npm run start
or
# watch mode
$ npm run start:dev
or
# production mode
$ npm run start:prod
After the docker environment has successfully spun up, configure Keycloak to setup a client.
Configure a client with the appropriate details:
- Access keycloak administration console via
http://localhost:9080/admin
and login using usernameadmin
and passwordadmin
. - Create a new realm, by default you are logged into the
master
realm. From the side menu clickmaster
in the dropdown menu and clickCreate Realm
. Name itpokemon
(lowercase) and setEnable
toOn
and clickCreate
. - After creating the new realm, Keycloak should switch you into that realm, if not navigate to it from the dropdown menu.
- From the side menu click
Clients
-->Create client
. Usepokemon-service
as theClient ID
,Pokemon Service
as theName
and clickNext
. - For the Capability config make sure
Client authentication
is OFF so the OIDC client is set to public access type. For theAuthentication Flow
we will enableAuthorization Code Flow
andResource Owner Password Credentials Grant
to generate tokens for this client. Once done clickNext
. - Under
Login settings
use the configuration below and clickSave
.
- Root URL:
http://localhost:8000
- Home URL:
http://localhost:8000/swagger
- Valid redirect URIs:
*
- Web origins:
*
- After clicking
Save
Keycloak navigates you to theClient details
page forpokemon-service
. - Create a new User inside of the
pokemon
realm. Click onUsers
in the side menu and clickAdd user
. - Use this configuration (ignore the other fields) and click
Create
:
- Username: pokemonuser
- Email verified: Yes
- Keycloak will navigate you to the
User details
page forpokemonuser
after clickingCreate
. Now click onCredentials
andSet password
. - Use the password
pokemonuser
and set Temporary toOff
, clickSave
andSave password
to confirm.
After these steps are completed proceed to Kong.
Due to using the free version of Kong, we are unable to use their supported OpenID Connect plugin. As an alternative we are using an open source OpenID Connect plugin, which unfortunately is no longer maintained but still usable using a forked project and image.
NOTE: If you choose to use confidential access type
instead of public access type
for Client Authentication
use the Client Secret from Credentials
in pokemon-service
Client Details for client_secret
in config/kong/kong.yaml
.
- In the
kong.yaml
file inside of./config/kong
, replace<CHANGE_ME>
with the IP Address assigned to your network interface.
plugins:
- name: oidc
config:
client_id: 'pokemon-service'
client_secret: '<update if using client authentication confidential access type for OIDC>'
realm: pokemon
introspection_endpoint: 'http://<CHANGE_ME>/realms/pokemon/protocol/openid-connect/token/introspect'
discovery: 'http://<CHANGE_ME>/realms/pokemon/.well-known/openid-configuration'
- Restart the kong api gateway using
docker compose up -d kong-api-gateway
. - Proceed to Usage,
After completing the configurations in Keycloak and Kong from the steps above, you can access the exposed Swagger UI from the pokemon-service sitting behind the Kong API Gateway after successful authentication.
Access the Swagger UI via http://localhost:8000/api.