package web import ( "fmt" "net/http" "time" "github.com/golang-jwt/jwt" "github.com/hashicorp/uuid" ) var ( tokens = map[string]string{} ) type TokenRequest struct { GrantType string Code string RedirectUri string } type TokenResponse struct { AccessToken string TokenType string RefreshToken string ExpiresIn int IdToken string } func (h *HttpContext) Token(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { tr := &TokenRequest{ GrantType: r.FormValue("grant_type"), Code: r.FormValue("code"), RedirectUri: r.FormValue("redirect_uri"), } if tr.GrantType == "authorization_code" { // Authorization Code Flow https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth r := &TokenResponse{ AccessToken: tokens[tr.Code], TokenType: "Bearer", RefreshToken: "TODO::", ExpiresIn: 3600, IdToken: h.createIdToken(r.FormValue("client_id")), } w.Header().Set("Content-Type", "application/json") w.Header().Set("Cache-Control", "no-store") w.Header().Set("Pragma", "no-cache") 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) } else { w.WriteHeader(http.StatusNotFound) fmt.Fprintf(w, "Not Found\n") } } } func (h *HttpContext) createIdToken(clientId string) string { now := time.Now() if clientId == "" { clientId = "clientId" } expiresAt := now.Add(time.Hour * time.Duration(1)) idToken := jwt.NewWithClaims(jwt.SigningMethodRS256, &jwt.StandardClaims{ Issuer: h.cfg.Issuer, Subject: "1", Audience: clientId, ExpiresAt: expiresAt.Unix(), NotBefore: now.Unix(), IssuedAt: now.Unix(), Id: uuid.GenerateUUID(), }) key, _ := jwt.ParseRSAPrivateKeyFromPEM(h.cfg.KeyData) signedIdToken, _ := idToken.SignedString(key) return signedIdToken }