Skip to content

Commit ba76f85

Browse files
author
Patrick Koss
committed
add readme
1 parent 0b29025 commit ba76f85

File tree

5 files changed

+96
-23
lines changed

5 files changed

+96
-23
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ build:
1919

2020
.PHONY: docker-build
2121
docker-build:
22-
CGO_ENABLED=0 go build -ldflags "-s -w" -o ./bin/fake-jwt-server -v cmd/fakejwtserver/main.go
22+
GOOS=linux CGO_ENABLED=0 go build -ldflags "-s -w" -o ./fake-jwt-server -v cmd/fakejwtserver/main.go
2323
docker build -t $(IMG) -f Dockerfile .
2424
rm fake-jwt-server
2525

README.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,41 @@
1-
# fake-jwt-server
1+
# Introduction
2+
3+
A straightforward mock-up of an identity provider (IDP) is designed to issue JWTs, enhancing the security of
4+
communications between services.
5+
6+
![fake-jwt-server-illustration](./media/fake-jwt-illustration.png)
7+
8+
To safeguard service interactions, various methods are available such as mutual TLS, basic authentication, or bearer
9+
authentication, to name a few. In bearer authentication, a token is required from an IDP, like Keycloak or Okta, through
10+
the client credentials grant of OAuth 2.0. Once the JWT is acquired, it can be transmitted in the authorization header
11+
when a service communicates with another. The recipient service can then verify the token using the IDP's public key.
12+
During local development or integration testing, utilizing a real IDP may not be desirable. This is where the concept of
13+
a fake-jwt-server is introduced. It's a basic version of an IDP that issues JWTs for OAuth flows and provides a public
14+
key endpoint for token verification.
15+
16+
# Running the Server
17+
18+
To launch the server in a Docker container, execute the following command:
19+
20+
```bash
21+
docker run -p 8008:8008 ghcr.io/stackitcloud/fake-jwt-server:v0.1.0
22+
```
23+
24+
This command initializes the server on port 8008. The public key can be accessed
25+
at http://localhost:8008/.well-known/jwks.json, and the OAuth token endpoint is available
26+
at http://localhost:8008/token.
27+
28+
# Configuration
29+
30+
The server's settings can be adjusted using specified environment variables and flags.
31+
32+
| Environment Variable | Flag | Description |
33+
|----------------------|------------------------|---------------------------------------------------------------------------|
34+
| `PORT` | `--port` | The port the server listens on. Defaults to `8008`. |
35+
| `ISSUER` | `--issuer` | The issuer of the tokens. Defaults to `test`. |
36+
| `AUDIENCE` | `--audience ` | The audience of the tokens. Defaults to `test `. |
37+
| `SUBJECT` | `--subject` | The subject of the tokens. Defaults to `test` |
38+
| `ID` | `--id` | The id of the tokens. Defaults to `test`. |
39+
| `EXPIRES_IN_MINUTES` | `--expires-in-minutes` | The expiration time of the JWT tokens in minutes. Defaults to `52560000`. |
40+
| `GRAND_TYPE` | `--grand-type` | The grand type of the JWT tokens. Defaults to `client_credentials`. |
41+
| `EMAIL` | `--email` | The email of the JWT token in minutes. Defaults to `test@example.com`. |

cmd/fakejwtserver/cmd/root.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"log"
66
"strings"
7+
"time"
78

89
"github.com/spf13/cobra"
910
"github.com/spf13/pflag"
@@ -13,11 +14,14 @@ import (
1314
)
1415

1516
var (
16-
audience string
17-
issuer string
18-
subject string
19-
port int
20-
id string
17+
audience string
18+
issuer string
19+
subject string
20+
port int
21+
id string
22+
email string
23+
grandType string
24+
expiresInMinutes int
2125
)
2226

2327
var rootCmd = &cobra.Command{
@@ -31,6 +35,9 @@ var rootCmd = &cobra.Command{
3135
fakeJwtServer.WithSubject(subject)
3236
fakeJwtServer.WithID(id)
3337
fakeJwtServer.WithPort(port)
38+
fakeJwtServer.WithEmail(email)
39+
fakeJwtServer.WithGrandType(grandType)
40+
fakeJwtServer.WithExpires(time.Duration(expiresInMinutes))
3441

3542
err := fakeJwtServer.Serve()
3643
if err != nil {
@@ -46,11 +53,14 @@ func Execute() error {
4653
func init() {
4754
cobra.OnInitialize(initConfig)
4855

49-
rootCmd.PersistentFlags().StringVar(&audience, "audience", "product", "The audience of the JWT token")
50-
rootCmd.PersistentFlags().StringVar(&issuer, "issuer", "product", "The issuer of the JWT token")
56+
rootCmd.PersistentFlags().StringVar(&audience, "audience", "test", "The audience of the JWT token")
57+
rootCmd.PersistentFlags().StringVar(&issuer, "issuer", "test", "The issuer of the JWT token")
5158
rootCmd.PersistentFlags().StringVar(&subject, "subject", "test", "The subject of the JWT token")
5259
rootCmd.PersistentFlags().StringVar(&id, "id", "test", "The id of the JWT token")
5360
rootCmd.PersistentFlags().IntVar(&port, "port", 8008, "The port the server should listen on")
61+
rootCmd.PersistentFlags().StringVar(&email, "email", "test@example.com", "The email of the JWT token")
62+
rootCmd.PersistentFlags().StringVar(&grandType, "grand-type", "client_credentials", "The grand type of the JWT token")
63+
rootCmd.PersistentFlags().IntVar(&expiresInMinutes, "expires-in-minutes", 24*365*100*60, "The expiration time of the JWT token in minutes")
5464
}
5565

5666
func initConfig() {

media/fake-jwt-illustration.png

91.9 KB
Loading

server/server.go

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -141,19 +141,18 @@ type FakeClaims struct {
141141
}
142142

143143
func (f *FakeJWTServer) createJsonWebToken() (string, error) {
144-
const years = 100
145144
claims := FakeClaims{
146145
RegisteredClaims: jwt.RegisteredClaims{
147146
Issuer: f.config.Issuer,
148147
Subject: f.config.Subject,
149148
Audience: jwt.ClaimStrings{f.config.Audience},
150-
ExpiresAt: jwt.NewNumericDate(time.Now().AddDate(years, 0, 0)),
149+
ExpiresAt: jwt.NewNumericDate(time.Now().Add(f.config.Expires)),
151150
NotBefore: jwt.NewNumericDate(time.Now().AddDate(0, 0, -1)),
152151
IssuedAt: jwt.NewNumericDate(time.Now()),
153152
ID: f.config.ID,
154153
},
155-
Email: "test@stackit.cloud",
156-
GrantType: "client_credentials",
154+
Email: f.config.Email,
155+
GrantType: f.config.GrandType,
157156
}
158157
token := jwt.NewWithClaims(jwt.SigningMethodRS512, claims)
159158
token.Header[jwk.KeyIDKey] = f.jsonWebKey.KeyID()
@@ -166,11 +165,14 @@ func (f *FakeJWTServer) createJsonWebToken() (string, error) {
166165
}
167166

168167
type Config struct {
169-
Issuer string
170-
Subject string
171-
Audience string
172-
ID string
173-
Port int
168+
Issuer string
169+
Subject string
170+
Audience string
171+
ID string
172+
Port int
173+
Expires time.Duration
174+
Email string
175+
GrandType string
174176
}
175177

176178
func NewFakeJwtServer() *FakeJWTServer {
@@ -194,11 +196,14 @@ func NewFakeJwtServer() *FakeJWTServer {
194196
jsonWebKey: jsonWebKey,
195197
publicKeySet: publicKeySet,
196198
config: Config{
197-
Issuer: "product",
198-
Subject: "test",
199-
Audience: "product",
200-
ID: "test",
201-
Port: 8008,
199+
Issuer: "test",
200+
Subject: "test",
201+
Audience: "test",
202+
ID: "test",
203+
Port: 8008,
204+
Expires: 24 * 365 * 100 * time.Hour,
205+
Email: "test@example.com",
206+
GrandType: "client_credentials",
202207
},
203208
}
204209
}
@@ -233,6 +238,24 @@ func (f *FakeJWTServer) WithPort(port int) *FakeJWTServer {
233238
return f
234239
}
235240

241+
func (f *FakeJWTServer) WithExpires(expires time.Duration) *FakeJWTServer {
242+
f.config.Expires = expires
243+
244+
return f
245+
}
246+
247+
func (f *FakeJWTServer) WithEmail(email string) *FakeJWTServer {
248+
f.config.Email = email
249+
250+
return f
251+
}
252+
253+
func (f *FakeJWTServer) WithGrandType(grantType string) *FakeJWTServer {
254+
f.config.GrandType = grantType
255+
256+
return f
257+
}
258+
236259
func (f *FakeJWTServer) Serve() error {
237260
mux := http.NewServeMux()
238261
mux.HandleFunc("/token", f.TokenHandler)

0 commit comments

Comments
 (0)