main
1package web
2
3import (
4 "fmt"
5 "net/http"
6 "time"
7
8 "github.com/golang-jwt/jwt"
9 "github.com/hashicorp/uuid"
10)
11
12var (
13 tokens = map[string]string{}
14)
15
16type TokenRequest struct {
17 GrantType string
18 Code string
19 RedirectUri string
20}
21
22type TokenResponse struct {
23 AccessToken string
24 TokenType string
25 RefreshToken string
26 ExpiresIn int
27 IdToken string
28}
29
30func (h *HttpContext) Token(w http.ResponseWriter, r *http.Request) {
31 if r.Method == "POST" {
32 tr := &TokenRequest{
33 GrantType: r.FormValue("grant_type"),
34 Code: r.FormValue("code"),
35 RedirectUri: r.FormValue("redirect_uri"),
36 }
37 if tr.GrantType == "authorization_code" {
38 // Authorization Code Flow https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth
39 r := &TokenResponse{
40 AccessToken: tokens[tr.Code],
41 TokenType: "Bearer",
42 RefreshToken: "TODO::",
43 ExpiresIn: 3600,
44 IdToken: h.createIdToken(r.FormValue("client_id")),
45 }
46
47 w.Header().Set("Content-Type", "application/json")
48 w.Header().Set("Cache-Control", "no-store")
49 w.Header().Set("Pragma", "no-cache")
50 fmt.Fprintf(w, `{"access_token": "%s","token_type": "%s","refresh_token": "%s","expires_in": %d,"id_token": "%s"}`, r.AccessToken, r.TokenType, r.RefreshToken, r.ExpiresIn, r.IdToken)
51 } else {
52 w.WriteHeader(http.StatusNotFound)
53 fmt.Fprintf(w, "Not Found\n")
54 }
55 }
56}
57
58func (h *HttpContext) createIdToken(clientId string) string {
59 now := time.Now()
60 if clientId == "" {
61 clientId = "clientId"
62 }
63 expiresAt := now.Add(time.Hour * time.Duration(1))
64 idToken := jwt.NewWithClaims(jwt.SigningMethodRS256, &jwt.StandardClaims{
65 Issuer: h.cfg.Issuer,
66 Subject: "1",
67 Audience: clientId,
68 ExpiresAt: expiresAt.Unix(),
69 NotBefore: now.Unix(),
70 IssuedAt: now.Unix(),
71 Id: uuid.GenerateUUID(),
72 })
73
74 key, _ := jwt.ParseRSAPrivateKeyFromPEM(h.cfg.KeyData)
75 signedIdToken, _ := idToken.SignedString(key)
76 return signedIdToken
77}