Json Web Token / oauth_token / auth_token
-
What?
This is open standard (RFC 7519) used for securely transmitting information between two parties as a JSON object.
Mostly used for authentication.
Usage? For authentication on the web, ie authentication to RESTFul API
Disecting token
-
JWTs consist of three parts: header + payload + signature, concatenated by dot .
jwt-token = header.payload.signature
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6IiIsImV4cCI6MTc0MDU1OTk2NX0.Dck0cV04Vv7G6ciMt2qvE5_fS2ZMpl5aFuXwKNnD3M0"}
How header, payload, Signature are calculated?
- A JWT is assigned to user as a authentication token
Header = Base64encode(algo+type)
struct st = {
"alg": "HS256",
"typ": "JWT",
}
header = base64Encode(st)
Payload = Base64encode(email+timestamp)
struct st = {
"email": email,
"exp": timestamp_to_expiry
}
payload = base64Encode(st)
Signature
HMAC_SHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
Complete Code
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"strings"
"time"
)
var jwtSecret = []byte("your-secret-key") // Use the same secret key
// Function to base64 URL encode a string
func base64UrlEncode(data []byte) string {
return strings.TrimRight(base64.URLEncoding.EncodeToString(data), "=")
}
// Function to create JWT header manually
func JWTHeader() string {
header := map[string]string{
"alg": "HS256",
"typ": "JWT",
}
headerJSON, _ := json.Marshal(header)
return base64UrlEncode(headerJSON)
}
// Function to create JWT payload manually
func JWTPayload(email string) string {
payload := map[string]interface{}{
"email": email,
"exp": time.Now().Add(time.Hour * 24).Unix(), // 24-hour expiry
}
payloadJSON, _ := json.Marshal(payload)
return base64UrlEncode(payloadJSON)
}
// Function to create JWT signature manually
func JWTSignature(email string) string {
headerEncoded := JWTHeader()
payloadEncoded := JWTPayload(email)
signatureInput := headerEncoded + "." + payloadEncoded
h := hmac.New(sha256.New, jwtSecret)
h.Write([]byte(signatureInput))
return base64UrlEncode(h.Sum(nil))
}
func generateManualJWT(email string, owner bool) string {
return JWTHeader() + "." + JWTPayload(email) + "." + JWTSignature(email)
}
func main() {
jwt := generateManualJWT("test@example.com")
fmt.Println("Generated JWT:", jwt)
}
How JWTs are used for authentication
sequenceDiagram
rect rgb(236, 232, 242)
participant dns as DNS
participant cdn as CDN
participant ub as User-Browser
box AWS
participant lb as LoadBalancer
participant as as Application Server
RESTFul Service
participant auth as Auth_Service
end
participant idp as IDP
note over ub: HTTP GET test.com
ub ->> dns: IP of test.com
dns ->> ub: IP of CDN
ub ->> cdn: HTTP GET test.com
cdn ->> ub: Home Page
note over ub: User enters username,pass
ub ->> lb: HTTP GET test.com(user,pass)
lb ->> as: HTTP GET test.com(user,pass)
as ->> ub: HTTP Redirect http://auth_svc
ub ->> auth: http://auth_svc?user?pass
auth ->> idp: ?user?pass
idp ->> auth: SAML Assertion(Authenticated)
auth ->> ub: JWT Token(Json Object)
note over auth:JWT=(header + payload(username)
+ signature(Digital signature of payload))
note over ub: Stores JWT in cookie or cache
ub ->> as: CRUD(header(bearer token=JWT) + Body)
note over as: JWT expiry in 5 hours
Reissue JWT
end