Validate JWT in your application server
Authenticate the incoming HTTP requests by validating JWT in your application server
In this section, we will go through how to decode the JWT token to obtain the currently logged-in user.
Before we start, make sure the option Issue JWT as access token is enabled in your Application settings in the Portal.

Find the JSON Web Key Sets (JWKS) endpoint

This Discovery endpoint serves a JSON document containing the OpenID Connect configuration of your app. It includes the authorization endpoint, the token endpoint and the JWKS endpoint.
https://<YOUR_AUTHGEAR_ENDPOINT>/.well-known/openid-configuration
The JSON Web Key Sets (JWKS) endpoint can be found in jwk_url in the configuration.

Decode user from an access token

Follow this step-by-step example to verify and decode the JWT token.
Python
Go
Node.js

Step 1: Install packages

1
pip install cryptography
2
pip install PyJWT
Copied!

Step 2: Find the JSON Web Key Sets (JWKS) endpoint

Define a function to find the JWKS endpoint from the OpenID Connect configuration. Use your Authgear endpoint as base_address
1
import json
2
from contextlib import closing
3
from urllib.request import urlopen
4
5
base_address = "https://<your_app_endpoint>"
6
7
def fetch_jwks_uri(base_address):
8
doc_url = base_address + "/.well-known/openid-configuration"
9
with closing(urlopen(doc_url)) as f:
10
doc = json.load(f)
11
jwks_uri = doc["jwks_uri"]
12
if not jwks_uri:
13
raise Exception('Failed to fetch jwks uri.')
14
return jwks_uri
Copied!

Step 3: Get JWT token from the Authorization header

Define a function to extract the access token from the Authorization header in the incoming request. It should look like Authorization: Bearer <access_token>.
1
def parse_header(authz_header):
2
parts = authz_header.split(" ")
3
if len(parts) != 2:
4
return
5
6
scheme = parts[0]
7
if scheme.lower() != "bearer":
8
return
9
10
return parts[1]
Copied!

Step 4: Verify and decode the JWT token

Here show an example of using Flask web framework to guard a path. You may need to adjust some of the codes to suit your technologies.
1
from flask import request
2
import jwt
3
from jwt import PyJWKClient
4
5
@app.route("/hello")
6
def hello():
7
authz_header = request.headers.get("Authorization")
8
if not authz_header:
9
return {
10
"message": "authz header not found"
11
}
12
13
# get jwt token from Authorization header
14
token = parse_header(authz_header)
15
if token:
16
try:
17
# fetch jwks_uri from the Authgear Discovery Endpoint
18
jwks_uri = fetch_jwks_uri(base_address)
19
# Reuse PyJWKClient for better performance
20
jwks_client = PyJWKClient(jwks_uri)
21
signing_key = jwks_client.get_signing_key_from_jwt(token)
22
user_data = jwt.decode(
23
token,
24
signing_key.key,
25
algorithms=["RS256"],
26
audience=base_address,
27
options={"verify_exp": True},
28
)
29
return {
30
"message": "Hello!",
31
"user_data": user_data
32
}
33
except:
34
return {
35
"message": "JWT decode failed"
36
}
37
else:
38
return {
39
"message": "no token"
40
}
Copied!
Use your Authgear endpoint as base_address
1
import (
2
"context"
3
"encoding/json"
4
"fmt"
5
"net/http"
6
"regexp"
7
"time"
8
9
"github.com/lestrrat-go/jwx/jwk"
10
"github.com/lestrrat-go/jwx/jwt"
11
)
12
13
14
var (
15
authzHeaderRegexp = regexp.MustCompile("(?i)^Bearer (.*)quot;)
16
baseAddress = "https://<your_app_endpoint>"
17
)
18
19
type OIDCDiscoveryDocument struct {
20
JWKSURI string `json:"jwks_uri"`
21
}
22
23
func FetchOIDCDiscoveryDocument(endpoint string) (*OIDCDiscoveryDocument, error) {
24
resp, err := http.DefaultClient.Get(endpoint)
25
if err != nil {
26
return nil, err
27
}
28
defer resp.Body.Close()
29
30
if resp.StatusCode != http.StatusOK {
31
return nil, fmt.Errorf(
32
"failed to fetch discovery document: unexpected status code: %d",
33
resp.StatusCode,
34
)
35
}
36
37
var document OIDCDiscoveryDocument
38
err = json.NewDecoder(resp.Body).Decode(&document)
39
if err != nil {
40
return nil, err
41
}
42
return &document, nil
43
}
44
45
func FetchJWK(baseAddress string) (jwk.Set, error) {
46
doc, err := FetchOIDCDiscoveryDocument(
47
baseAddress + "/.well-known/openid-configuration",
48
)
49
if err != nil {
50
return nil, err
51
}
52
53
set, err := jwk.Fetch(context.Background(), doc.JWKSURI)
54
return set, err
55
}
56
57
// DecodeUser parse request Authorization header and obtain user id and claims
58
func DecodeUser(r *http.Request) (string, map[string]interface{}, error) {
59
// fetch jwks_uri from Authgear
60
// you can cache the value of jwks to have better performance
61
set, err := FetchJWK(baseAddress)
62
if err != nil {
63
return "", nil, fmt.Errorf("failed to fetch JWK: %s", err)
64
}
65
66
// get jwt token from Authorization header
67
authzHeader := r.Header.Get("Authorization")
68
match := authzHeaderRegexp.FindStringSubmatch(authzHeader)
69
if len(match) != 2 {
70
return "", nil, fmt.Errorf("no token")
71
}
72
73
// parse jwt token
74
token, err := jwt.ParseString(match[1], jwt.WithKeySet(set))
75
if err != nil {
76
return "", nil, fmt.Errorf("invalid token: %s", err)
77
}
78
79
// validate jwt token
80
err = jwt.Validate(token,
81
jwt.WithClock(jwt.ClockFunc(
82
func() time.Time { return time.Now().UTC() },
83
)),
84
jwt.WithAudience(baseAddress),
85
)
86
if err != nil {
87
return "", nil, fmt.Errorf("invalid token: %s", err)
88
}
89
90
return token.Subject(), token.PrivateClaims(), nil
91
}
92
93
func handler(w http.ResponseWriter, r *http.Request) {
94
// decode user example
95
userid, claims, err := DecodeUser(r)
96
isUserVerified, _ :=
97
claims["https://authgear.com/claims/user/is_verified"].(bool)
98
isAnonymousUser, _ :=
99
claims["https://authgear.com/claims/user/is_anonymous"].(bool)
100
101
// ... your handler logic
102
}
Copied!
TODO: Node.js example is coming soon
Here is an example demonstrates how to add authorization to an Express.js API

Step 1: Install dependencies

1
npm install --save express-jwt jwks-rsa
Copied!

Step 2: Configure the middleware

Step 3: Protect API Endpoints

Decode user from cookies

Validating JWT in your application server is currently only available for Token-based authentication.
For Cookie-based authentication, JWT in cookies is not supported yet. You can track the issue here.
Last modified 7mo ago