Skip to content

Commit 37a93cf

Browse files
authored
Release August 2025
* Added CI/CD for GitHub Workflows * Updated Postman collection and Fixed the API path * Added a new command `make build` to Makefile for purely building dockerfiles * Updated README doc with CI/CD badge and a few minor changes and a new Todos * Added a new container “Proxy” to distribute the traffic to Golang API supporting both TLS and Non-TLS Connections * Fixed TLS bug with Redis Container and Golang Client Connection through TLS * Resolved the flow for context and cancellation per request instead of instance of each service * Added a new endpoint `/healthz` to assess the health of API and determine the container health * Added a new method for Cache `PersistWithTimeToLive` that automatically removes the record after defined duration * Updated environment variables in separate file `.env` at the root of `deploy` under docker package
2 parents de34100 + 0a4fdd2 commit 37a93cf

File tree

23 files changed

+466
-191
lines changed

23 files changed

+466
-191
lines changed

.github/workflows/makefile.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Build & Tests
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
9+
jobs:
10+
build:
11+
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Build Dockerfiles
18+
run: make build

Collection.postman_collection.json

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,106 @@
11
{
22
"info": {
3-
"_postman_id": "8c2e7d7e-f96f-406c-99ff-632be03e1271",
3+
"_postman_id": "59bf083c-a877-459e-87f1-3786cd8b3dd6",
44
"name": "Oauth 2 Password Grant RESTful API Collection",
5-
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
5+
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
6+
"_exporter_id": "41408414"
67
},
78
"item": [
89
{
9-
"name": "Token Request",
10+
"name": "Healthz",
11+
"request": {
12+
"method": "GET",
13+
"header": [],
14+
"url": {
15+
"raw": "https://127.0.0.1/healthz",
16+
"protocol": "https",
17+
"host": [
18+
"127",
19+
"0",
20+
"0",
21+
"1"
22+
],
23+
"path": [
24+
"healthz"
25+
]
26+
}
27+
},
28+
"response": []
29+
},
30+
{
31+
"name": "Clients",
1032
"request": {
1133
"auth": {
1234
"type": "noauth"
1335
},
1436
"method": "POST",
1537
"header": [],
1638
"body": {
17-
"mode": "urlencoded",
18-
"urlencoded": [
19-
{
20-
"key": "grant_type",
21-
"value": "password",
22-
"type": "default"
23-
},
24-
{
25-
"key": "username",
26-
"value": "johndoe1",
27-
"type": "default"
28-
},
29-
{
30-
"key": "password",
31-
"value": "MyPassword!",
32-
"type": "default"
39+
"mode": "raw",
40+
"raw": "{\n \"username\": \"johndoe\",\n \"password\": \"MyPassword!\"\n}\n",
41+
"options": {
42+
"raw": {
43+
"language": "json"
3344
}
34-
]
45+
}
3546
},
3647
"url": {
37-
"raw": "127.0.0.1:8080/oauth2/token",
48+
"raw": "https://127.0.0.1/oauth2/clients",
49+
"protocol": "https",
3850
"host": [
3951
"127",
4052
"0",
4153
"0",
4254
"1"
4355
],
44-
"port": "8080",
4556
"path": [
46-
"oauth",
47-
"token"
57+
"oauth2",
58+
"clients"
4859
]
4960
}
5061
},
5162
"response": []
5263
},
5364
{
54-
"name": "Clients [Create]",
65+
"name": "Token Request",
5566
"request": {
5667
"auth": {
5768
"type": "noauth"
5869
},
5970
"method": "POST",
6071
"header": [],
6172
"body": {
62-
"mode": "raw",
63-
"raw": "{\n \"username\": \"johndoe1\",\n \"password\": \"MyPassword!\"\n}\n",
64-
"options": {
65-
"raw": {
66-
"language": "json"
73+
"mode": "urlencoded",
74+
"urlencoded": [
75+
{
76+
"key": "grant_type",
77+
"value": "password",
78+
"type": "default"
79+
},
80+
{
81+
"key": "username",
82+
"value": "johndoe",
83+
"type": "default"
84+
},
85+
{
86+
"key": "password",
87+
"value": "MyPassword!",
88+
"type": "default"
6789
}
68-
}
90+
]
6991
},
7092
"url": {
71-
"raw": "127.0.0.1:8080/oauth2/clients",
93+
"raw": "https://127.0.0.1/oauth2/token",
94+
"protocol": "https",
7295
"host": [
7396
"127",
7497
"0",
7598
"0",
7699
"1"
77100
],
78-
"port": "8080",
79101
"path": [
80-
"oauth",
81-
"clients"
102+
"oauth2",
103+
"token"
82104
]
83105
}
84106
},

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ help:
22
@awk 'BEGIN {FS = ":.*#"; printf "Usage: make \033[36m<target>\033[0m\n"} /^[a-zA-Z_-]+:.*?#/ { printf " \033[36m%-10s\033[0m %s\n", $$1, $$2 } /^#@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
33

44

5+
.PHONY: build
6+
build: # Builds all necessary Docker files for for OAuth Authentication services
7+
docker-compose -f ./deploy/docker/docker-compose.yml build --no-cache
8+
9+
510
.PHONY: deploy
611
deploy: # Deploys Services for OAuth Authentication
712
docker-compose -f ./deploy/docker/docker-compose.yml build

README.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
1-
# OAuth 2 Password Grant Type in Golang
2-
Implementation of standard OAuth V2 for Password Grant type in Golang
1+
# OAuth 2.1 Password Grant Type in Golang
2+
![workflow](https://github.com/syniol/golang-oauth-password-grant/actions/workflows/makefile.yml/badge.svg)
3+
4+
Implementation of standard OAuth 2.1 for Password Grant type in Golang
35
and its native HTTP server.
46

57

68
## Clients API
79
```text
810
POST oauth2/clients HTTP/1.1
9-
Host: 127.0.0.1:8080
11+
Host: 127.0.0.1
1012
Content-Type: application/json
1113
```
1214

1315
__Request:__
1416
```bash
15-
curl -k --location --request POST 'https://127.0.0.1:8080/oauth2/clients' \
17+
curl -k --location --request POST 'https://127.0.0.1/oauth2/clients' \
1618
--header 'Content-Type: application/json' \
1719
--data-raw '{
18-
"username": "johndoe1",
20+
"username": "johndoe2",
1921
"password": "johnspassword1"
2022
}'
2123
```
@@ -31,13 +33,13 @@ __Response:__
3133
## Token API
3234
```text
3335
POST oauth2/token HTTP/1.1
34-
Host: 127.0.0.1:8080
36+
Host: 127.0.0.1
3537
Content-Type: application/x-www-form-urlencoded
3638
```
3739

3840
__Request:__
3941
```bash
40-
curl -k --location --request POST 'https://127.0.0.1:8080/oauth2/token' \
42+
curl -k --location --request POST 'https://127.0.0.1/oauth2/token' \
4143
--header 'Content-Type: application/x-www-form-urlencoded' \
4244
--data-urlencode 'grant_type=password' \
4345
--data-urlencode 'username=johndoe1' \
@@ -71,19 +73,17 @@ local environment. You will need database & cache storage from docker; you could
7173

7274
![img](https://github.com/syniol/golang-oauth-password-grant/assets/68777073/5c24392a-29df-41c2-8f11-fd32a1053222)
7375

74-
75-
7676
### Todos
77-
* [x] SSL For Postgres
78-
* [x] SSL & Password for Redis
79-
* [x] Cert for Creation of Token (Could be from Infra or Inside the code)
80-
* [x] TLS Server Listener
81-
* [ ] Use Docker Secret to share passwords
77+
* [ ] Add more documents about this repository and RFC Standard for OAuth 2.1 especially for `password_grant`
78+
* [ ] Convert Http Error response to JSON response `errors: []`
79+
* [ ] Investigate possibility of volume share for Redis & Go (app) to share TLS certs
80+
* [ ] Separate the Docker network for proxy and app to exclude Database (Postgres) & Cache (Redis)
81+
* [ ] Increase code coverage
8282

8383

8484
#### Credits
8585
Author: [Hadi Tajallaei](mailto:hadi@syniol.com)
8686

87-
Copyright &copy; 2023 Syniol Limited. All rights reserved.
87+
Copyright &copy; 2023-2025 Syniol Limited. All rights reserved.
8888

8989
_Please see a [LICENSE file](https://github.com/syniol/golang-oauth-password-grant/blob/main/LICENSE)_

deploy/docker/.env

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
POSTGRES_HOST=database
2+
POSTGRES_USER=oauth_usr
3+
POSTGRES_PASSWORD=DummyPassword1
4+
POSTGRES_DB=oauth
5+
REDIS_TLS_CERT_FILE=/usr/local/etc/redis/tls/redis.crt
6+
REDIS_TLS_KEY_FILE=/usr/local/etc/redis/tls/redis.key
7+
REDIS_TLS_CA_FILE=/usr/local/etc/redis/tls/ca.crt

deploy/docker/docker-compose.debug.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
version: "3"
21
services:
32
database:
43
ports:

deploy/docker/docker-compose.yml

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,86 @@
1-
version: "3"
21
services:
2+
proxy:
3+
image: oauth_nginx:1.22
4+
build:
5+
context: ../..
6+
dockerfile: deploy/docker/nginx/Dockerfile
7+
container_name: oauth_proxy
8+
restart: unless-stopped
9+
ports:
10+
- "80:80"
11+
- "443:443"
12+
healthcheck:
13+
test: curl -k -s -o /dev/null -w "%{http_code}" https://proxy/healthz | grep 200 || exit 1
14+
interval: 10s
15+
timeout: 5s
16+
retries: 3
17+
networks:
18+
- oauth_authentication_net
19+
320
app:
421
image: oauth_golang:1.18
522
build:
623
context: ../..
724
dockerfile: deploy/docker/golang/Dockerfile
825
container_name: oauth_app
26+
restart: unless-stopped
27+
depends_on:
28+
- database
29+
- cache
930
environment:
10-
POSTGRES_USER: oauth_usr
11-
POSTGRES_PASSWORD: DummyPassword1
12-
POSTGRES_DB: oauth
13-
REDIS_PASSWORD: SyniolIsTheFuture
14-
ports:
15-
- "8080:8080"
31+
POSTGRES_HOST: ${POSTGRES_HOST}
32+
POSTGRES_USER: ${POSTGRES_USER}
33+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
34+
POSTGRES_DB: ${POSTGRES_DB}
35+
REDIS_TLS_CERT_FILE: ${REDIS_TLS_CERT_FILE}
36+
REDIS_TLS_KEY_FILE: ${REDIS_TLS_KEY_FILE}
37+
REDIS_TLS_CA_FILE: ${REDIS_TLS_CA_FILE}
1638
networks:
17-
- oauth_authentication
39+
- oauth_authentication_net
1840

1941
database:
2042
image: oauth_postgres:14
2143
build:
2244
context: ../..
2345
dockerfile: deploy/docker/postgres/Dockerfile
2446
container_name: oauth_db
47+
restart: unless-stopped
2548
environment:
26-
POSTGRES_PASSWORD: DummyPassword1
27-
POSTGRES_USER: oauth_usr
28-
POSTGRES_DB: oauth
49+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
50+
POSTGRES_USER: ${POSTGRES_USER}
51+
POSTGRES_DB: ${POSTGRES_DB}
52+
healthcheck:
53+
test: [ "CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}" ]
54+
interval: 10s
55+
timeout: 5s
56+
retries: 3
2957
volumes:
3058
- database_data:/var/lib/postgresql/data
3159
networks:
32-
- oauth_authentication
60+
- oauth_authentication_net
3361

3462
cache:
3563
image: oauth_redis:6
3664
build:
3765
context: ../..
3866
dockerfile: deploy/docker/redis/Dockerfile
3967
container_name: oauth_cache
40-
environment:
41-
REDIS_PASSWORD: SyniolIsTheFuture
68+
restart: unless-stopped
69+
healthcheck:
70+
test: [ "CMD-SHELL", "redis-cli --tls --cert $${REDIS_TLS_CERT_FILE} --key $${REDIS_TLS_KEY_FILE} --cacert $${REDIS_TLS_CA_FILE} --insecure PING | grep PONG" ]
71+
interval: 10s
72+
timeout: 5s
73+
retries: 3
4274
volumes:
4375
- cache_data:/data
4476
networks:
45-
- oauth_authentication
77+
- oauth_authentication_net
4678

4779
volumes:
4880
database_data:
81+
name: oauth_database_data
4982
cache_data:
83+
name: oauth_cache_data
5084

5185
networks:
52-
oauth_authentication:
53-
driver: bridge
86+
oauth_authentication_net:

deploy/docker/golang/Dockerfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ RUN addgroup -S myapp \
2929
RUN chown myapp:myapp server.crt \
3030
&& chown myapp:myapp server.key
3131

32+
COPY ./deploy/docker/redis/tls/ /usr/local/etc/redis/tls/
33+
34+
WORKDIR /usr/local/etc/redis/tls
35+
36+
RUN chown myapp:myapp redis.crt \
37+
&& chown myapp:myapp redis.key \
38+
&& chown myapp:myapp ca.crt
39+
3240

3341

3442
FROM scratch
@@ -39,6 +47,9 @@ COPY --from=builder /var/local/app/server.key .
3947
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
4048

4149
COPY --from=builder /etc/passwd /etc/passwd
50+
51+
COPY --from=builder /usr/local/etc/redis/tls/ /usr/local/etc/redis/tls/
52+
4253
USER myapp
4354

4455
ENTRYPOINT ["/restapi"]

0 commit comments

Comments
 (0)