1/* 2This is an example application to demonstrate parsing an ID Token. 3*/ 4package main 5 6import ( 7 "encoding/json" 8 "log" 9 "net/http" 10 "os" 11 12 oidc "github.com/coreos/go-oidc" 13 14 "golang.org/x/net/context" 15 "golang.org/x/oauth2" 16) 17 18var ( 19 clientID = os.Getenv("GOOGLE_OAUTH2_CLIENT_ID") 20 clientSecret = os.Getenv("GOOGLE_OAUTH2_CLIENT_SECRET") 21) 22 23func main() { 24 ctx := context.Background() 25 26 provider, err := oidc.NewProvider(ctx, "https://accounts.google.com") 27 if err != nil { 28 log.Fatal(err) 29 } 30 oidcConfig := &oidc.Config{ 31 ClientID: clientID, 32 } 33 verifier := provider.Verifier(oidcConfig) 34 35 config := oauth2.Config{ 36 ClientID: clientID, 37 ClientSecret: clientSecret, 38 Endpoint: provider.Endpoint(), 39 RedirectURL: "http://127.0.0.1:5556/auth/google/callback", 40 Scopes: []string{oidc.ScopeOpenID, "profile", "email"}, 41 } 42 43 state := "foobar" // Don't do this in production. 44 45 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 46 http.Redirect(w, r, config.AuthCodeURL(state), http.StatusFound) 47 }) 48 49 http.HandleFunc("/auth/google/callback", func(w http.ResponseWriter, r *http.Request) { 50 if r.URL.Query().Get("state") != state { 51 http.Error(w, "state did not match", http.StatusBadRequest) 52 return 53 } 54 55 oauth2Token, err := config.Exchange(ctx, r.URL.Query().Get("code")) 56 if err != nil { 57 http.Error(w, "Failed to exchange token: "+err.Error(), http.StatusInternalServerError) 58 return 59 } 60 rawIDToken, ok := oauth2Token.Extra("id_token").(string) 61 if !ok { 62 http.Error(w, "No id_token field in oauth2 token.", http.StatusInternalServerError) 63 return 64 } 65 idToken, err := verifier.Verify(ctx, rawIDToken) 66 if err != nil { 67 http.Error(w, "Failed to verify ID Token: "+err.Error(), http.StatusInternalServerError) 68 return 69 } 70 71 oauth2Token.AccessToken = "*REDACTED*" 72 73 resp := struct { 74 OAuth2Token *oauth2.Token 75 IDTokenClaims *json.RawMessage // ID Token payload is just JSON. 76 }{oauth2Token, new(json.RawMessage)} 77 78 if err := idToken.Claims(&resp.IDTokenClaims); err != nil { 79 http.Error(w, err.Error(), http.StatusInternalServerError) 80 return 81 } 82 data, err := json.MarshalIndent(resp, "", " ") 83 if err != nil { 84 http.Error(w, err.Error(), http.StatusInternalServerError) 85 return 86 } 87 w.Write(data) 88 }) 89 90 log.Printf("listening on http://%s/", "127.0.0.1:5556") 91 log.Fatal(http.ListenAndServe("127.0.0.1:5556", nil)) 92} 93