├── .gitignore ├── routes ├── logout │ ├── go.mod │ └── logout.go ├── templates │ ├── go.mod │ └── templates.go ├── home │ ├── go.mod │ ├── home.go │ └── home.html ├── middlewares │ ├── go.mod │ ├── isAuthenticated.go │ └── go.sum ├── login │ ├── go.mod │ ├── login.go │ └── go.sum ├── user │ ├── go.mod │ ├── user.go │ ├── go.sum │ └── user.html └── callback │ ├── go.mod │ ├── callback.go │ └── go.sum ├── .dockerignore ├── exec.ps1 ├── .env.sample ├── exec.sh ├── main.go ├── app ├── go.mod ├── go.sum └── app.go ├── public └── user.js ├── Dockerfile ├── auth ├── go.mod ├── auth.go └── go.sum ├── README.md ├── go.mod ├── server.go └── go.sum /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .DS_Store 3 | src/ 4 | pkg/ 5 | AADGOWEBAPP -------------------------------------------------------------------------------- /routes/logout/go.mod: -------------------------------------------------------------------------------- 1 | module AADGOWEBAPP/routes/logout 2 | 3 | go 1.12 4 | -------------------------------------------------------------------------------- /routes/templates/go.mod: -------------------------------------------------------------------------------- 1 | module AADGOWEBAPP/routes/templates 2 | 3 | go 1.12 4 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .env.example 2 | .gitignore 3 | README.md 4 | exec.sh 5 | exec.ps1 6 | src/ 7 | pkg/ 8 | -------------------------------------------------------------------------------- /exec.ps1: -------------------------------------------------------------------------------- 1 | docker build -t aad-golang-webapp . 2 | docker run --env-file .env -p 3000:3000 -it aad-golang-webapp 3 | -------------------------------------------------------------------------------- /.env.sample: -------------------------------------------------------------------------------- 1 | tenantid=> 2 | clientid= 3 | clientsecret= 4 | callbackurl=http://localhost:3000/callback -------------------------------------------------------------------------------- /exec.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | docker build -t aad-golang-webapp . 3 | docker run --env-file .env -p 3000:3000 -it aad-golang-webapp 4 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "app" 5 | ) 6 | 7 | func main() { 8 | app.Init() 9 | StartServer() 10 | } 11 | -------------------------------------------------------------------------------- /routes/home/go.mod: -------------------------------------------------------------------------------- 1 | module AADGOWEBAPP/routes/home 2 | 3 | go 1.12 4 | 5 | require templates v0.0.0 6 | 7 | replace templates => ../templates 8 | -------------------------------------------------------------------------------- /routes/middlewares/go.mod: -------------------------------------------------------------------------------- 1 | module AADGOWEBAPP/routes/middlewares 2 | 3 | go 1.12 4 | 5 | require app v0.0.0 6 | 7 | replace app => ../../app 8 | -------------------------------------------------------------------------------- /app/go.mod: -------------------------------------------------------------------------------- 1 | module AADGOWEBAPP/app 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/gorilla/sessions v1.2.0 7 | github.com/joho/godotenv v1.3.0 8 | ) 9 | -------------------------------------------------------------------------------- /public/user.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $('.btn-logout').click(function(e) { 3 | Cookies.remove('auth-session'); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.12 2 | 3 | RUN mkdir /tmp/app 4 | ADD . /tmp/app 5 | WORKDIR /tmp/app 6 | 7 | RUN go build -o main . 8 | CMD ["/tmp/app/main"] 9 | EXPOSE 3000 -------------------------------------------------------------------------------- /routes/login/go.mod: -------------------------------------------------------------------------------- 1 | module AADGOWEBAPP/routes/login 2 | 3 | go 1.12 4 | 5 | require ( 6 | app v0.0.0 7 | auth v0.0.0 8 | ) 9 | 10 | replace app => ../../app 11 | 12 | replace auth => ../../auth 13 | -------------------------------------------------------------------------------- /routes/user/go.mod: -------------------------------------------------------------------------------- 1 | module AADGOWEBAPP/routes/user 2 | 3 | go 1.12 4 | 5 | require ( 6 | app v0.0.0 7 | templates v0.0.0 8 | ) 9 | 10 | replace app => ../../app 11 | 12 | replace templates => ../templates 13 | -------------------------------------------------------------------------------- /routes/home/home.go: -------------------------------------------------------------------------------- 1 | package home 2 | 3 | import ( 4 | "net/http" 5 | "templates" 6 | ) 7 | 8 | func HomeHandler(w http.ResponseWriter, r *http.Request) { 9 | templates.RenderTemplate(w, "home", nil) 10 | } 11 | -------------------------------------------------------------------------------- /routes/callback/go.mod: -------------------------------------------------------------------------------- 1 | module AADGOWEBAPP/routes/callback 2 | 3 | go 1.12 4 | 5 | require ( 6 | app v0.0.0 7 | auth v0.0.0 8 | github.com/coreos/go-oidc v2.1.0+incompatible 9 | ) 10 | 11 | replace app => ../../app 12 | 13 | replace auth => ../../auth 14 | -------------------------------------------------------------------------------- /auth/go.mod: -------------------------------------------------------------------------------- 1 | module AADGOWEBAPP/auth 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/coreos/go-oidc v2.1.0+incompatible 7 | github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect 8 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 // indirect 9 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 10 | gopkg.in/square/go-jose.v2 v2.3.1 // indirect 11 | ) 12 | -------------------------------------------------------------------------------- /routes/user/user.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "app" 5 | "net/http" 6 | "templates" 7 | ) 8 | 9 | func UserHandler(w http.ResponseWriter, r *http.Request) { 10 | 11 | session, err := app.Store.Get(r, "auth-session") 12 | if err != nil { 13 | http.Error(w, err.Error(), http.StatusInternalServerError) 14 | return 15 | } 16 | 17 | templates.RenderTemplate(w, "user", session.Values["profile"]) 18 | } 19 | -------------------------------------------------------------------------------- /routes/logout/logout.go: -------------------------------------------------------------------------------- 1 | package logout 2 | 3 | import ( 4 | "net/http" 5 | "net/url" 6 | "os" 7 | ) 8 | 9 | func LogoutHandler(w http.ResponseWriter, r *http.Request) { 10 | logoutUrl, err := url.Parse("https://login.microsoftonline.com/" + os.Getenv("tenantid") + "/oauth2/logout?client_id=" + os.Getenv("clientid")) 11 | if err != nil { 12 | http.Error(w, err.Error(), http.StatusInternalServerError) 13 | return 14 | } 15 | http.Redirect(w, r, logoutUrl.String(), http.StatusTemporaryRedirect) 16 | } 17 | -------------------------------------------------------------------------------- /routes/middlewares/isAuthenticated.go: -------------------------------------------------------------------------------- 1 | package middlewares 2 | 3 | import ( 4 | "app" 5 | "net/http" 6 | ) 7 | 8 | func IsAuthenticated(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 9 | session, err := app.Store.Get(r, "auth-session") 10 | if err != nil { 11 | http.Error(w, err.Error(), http.StatusInternalServerError) 12 | return 13 | } 14 | 15 | if _, ok := session.Values["profile"]; !ok { 16 | http.Redirect(w, r, "/", http.StatusSeeOther) 17 | } else { 18 | next(w, r) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/go.sum: -------------------------------------------------------------------------------- 1 | github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= 2 | github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= 3 | github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ= 4 | github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= 5 | github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= 6 | github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 7 | -------------------------------------------------------------------------------- /routes/user/go.sum: -------------------------------------------------------------------------------- 1 | github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= 2 | github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= 3 | github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ= 4 | github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= 5 | github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= 6 | github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 7 | -------------------------------------------------------------------------------- /app/app.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "encoding/gob" 5 | "log" 6 | "math" 7 | "os" 8 | 9 | "github.com/gorilla/sessions" 10 | "github.com/joho/godotenv" 11 | ) 12 | 13 | var ( 14 | Store *sessions.FilesystemStore 15 | ) 16 | 17 | func Init() error { 18 | err := godotenv.Load() 19 | if err != nil { 20 | log.Print(err.Error()) 21 | return err 22 | } 23 | 24 | Store = sessions.NewFilesystemStore(os.TempDir(), []byte("secret")) 25 | Store.MaxLength(math.MaxInt64) 26 | gob.Register(map[string]interface{}{}) 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /routes/middlewares/go.sum: -------------------------------------------------------------------------------- 1 | github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= 2 | github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= 3 | github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ= 4 | github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= 5 | github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= 6 | github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 7 | -------------------------------------------------------------------------------- /routes/templates/templates.go: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | "html/template" 5 | "net/http" 6 | "os" 7 | "path/filepath" 8 | ) 9 | 10 | func RenderTemplate(w http.ResponseWriter, tmpl string, data interface{}) { 11 | cwd, _ := os.Getwd() 12 | t, err := template.ParseFiles(filepath.Join( cwd, "./routes/" + tmpl + "/" + tmpl + ".html")) 13 | if err != nil { 14 | http.Error(w, err.Error(), http.StatusInternalServerError) 15 | return 16 | } 17 | err = t.Execute(w, data) 18 | if err != nil { 19 | http.Error(w, err.Error(), http.StatusInternalServerError) 20 | } 21 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Azure AD + Golang Web App Sample 2 | 3 | This sample shows how to use a Go web app to sign into using AAD. 4 | 5 | If you are looking for client credentials flow, managed identities or device code flow, you should check out Azure SDK at https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authorization 6 | 7 | ## Instructions 8 | 9 | 1. Register a new app in Azure AD 10 | 2. Add the "web" platform with redirect uri "http://localhost:3000/callback" 11 | 3. Generate a client secret 12 | 4. Rename .env.sample to .env and update values 13 | 14 | *To run* 15 | 1. Run `go build ./...` to build and install the Go dependencies. 16 | 2. Run `go run main.go server.go` to start the app 17 | 3. Point your browser to [http://localhost:3000/](http://localhost:3000/). 18 | 4. Login using your credentials. 19 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module AADGOWEBAPP 2 | 3 | go 1.12 4 | 5 | require ( 6 | app v0.0.0 7 | auth v0.0.0 8 | callback v0.0.0 9 | 10 | github.com/codegangsta/negroni v1.0.0 11 | github.com/coreos/go-oidc v2.2.1+incompatible 12 | github.com/gorilla/mux v1.8.0 13 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 14 | home v0.0.0 15 | login v0.0.0 16 | logout v0.0.0 17 | middlewares v0.0.0 18 | templates v0.0.0 19 | user v0.0.0 20 | ) 21 | 22 | replace app => ./app 23 | 24 | replace auth => ./auth 25 | 26 | replace callback => ./routes/callback 27 | 28 | replace home => ./routes/home 29 | 30 | replace login => ./routes/login 31 | 32 | replace logout => ./routes/logout 33 | 34 | replace middlewares => ./routes/middlewares 35 | 36 | replace user => ./routes/user 37 | 38 | replace templates => ./routes/templates 39 | -------------------------------------------------------------------------------- /routes/home/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |

AAD Go Lang!

14 |

This simple application will allow you to login using your AAD credentials.

15 |
16 |

Click the login button below.

17 | LogIn 18 |
19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /routes/user/user.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
12 |

AAD Go Lang!

13 |

Welcome {{.name}}. You are now logged in.

14 |
15 |

To logout, click the button below.

16 | Log out 17 |
18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/codegangsta/negroni" 8 | "github.com/gorilla/mux" 9 | 10 | "callback" 11 | "home" 12 | "login" 13 | "logout" 14 | "middlewares" 15 | "user" 16 | ) 17 | 18 | func StartServer() { 19 | r := mux.NewRouter() 20 | 21 | r.HandleFunc("/", home.HomeHandler) 22 | r.HandleFunc("/login", login.LoginHandler) 23 | r.HandleFunc("/logout", logout.LogoutHandler) 24 | r.HandleFunc("/callback", callback.CallbackHandler) 25 | r.Handle("/user", negroni.New( 26 | negroni.HandlerFunc(middlewares.IsAuthenticated), 27 | negroni.Wrap(http.HandlerFunc(user.UserHandler)), 28 | )) 29 | r.PathPrefix("/public/").Handler(http.StripPrefix("/public/", http.FileServer(http.Dir("public/")))) 30 | http.Handle("/", r) 31 | log.Print("Server listening on http://localhost:3000/") 32 | log.Fatal(http.ListenAndServe("0.0.0.0:3000", nil)) 33 | } 34 | -------------------------------------------------------------------------------- /auth/auth.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "os" 7 | 8 | oidc "github.com/coreos/go-oidc" 9 | "golang.org/x/oauth2" 10 | ) 11 | 12 | type Authenticator struct { 13 | Provider *oidc.Provider 14 | Config oauth2.Config 15 | Ctx context.Context 16 | } 17 | 18 | func NewAuthenticator() (*Authenticator, error) { 19 | ctx := context.Background() 20 | provider, err := oidc.NewProvider(ctx, "https://login.microsoftonline.com/"+os.Getenv("tenantid")+"/v2.0") 21 | if err != nil { 22 | log.Printf("failed to get provider: %v", err) 23 | return nil, err 24 | } 25 | 26 | conf := oauth2.Config{ 27 | ClientID: os.Getenv("clientid"), 28 | ClientSecret: os.Getenv("clientsecret"), 29 | RedirectURL: os.Getenv("callbackurl"), 30 | Endpoint: provider.Endpoint(), 31 | Scopes: []string{oidc.ScopeOpenID, "profile"}, 32 | } 33 | 34 | log.Print(conf) 35 | 36 | return &Authenticator{ 37 | Provider: provider, 38 | Config: conf, 39 | Ctx: ctx, 40 | }, nil 41 | } 42 | -------------------------------------------------------------------------------- /routes/login/login.go: -------------------------------------------------------------------------------- 1 | package login 2 | 3 | import ( 4 | "crypto/rand" 5 | "encoding/base64" 6 | "net/http" 7 | 8 | "app" 9 | "auth" 10 | ) 11 | 12 | func LoginHandler(w http.ResponseWriter, r *http.Request) { 13 | // Generate random state 14 | b := make([]byte, 32) 15 | _, err := rand.Read(b) 16 | 17 | if err != nil { 18 | http.Error(w, err.Error(), http.StatusInternalServerError) 19 | return 20 | } 21 | state := base64.StdEncoding.EncodeToString(b) 22 | 23 | session, err := app.Store.Get(r, "auth-session") 24 | 25 | if err != nil { 26 | http.Error(w, err.Error(), http.StatusInternalServerError) 27 | return 28 | } 29 | session.Values["state"] = state 30 | err = session.Save(r, w) 31 | if err != nil { 32 | http.Error(w, err.Error(), http.StatusInternalServerError) 33 | return 34 | } 35 | 36 | authenticator, err := auth.NewAuthenticator() 37 | 38 | if err != nil { 39 | http.Error(w, err.Error(), http.StatusInternalServerError) 40 | return 41 | } 42 | 43 | http.Redirect(w, r, authenticator.Config.AuthCodeURL(state), http.StatusTemporaryRedirect) 44 | } 45 | -------------------------------------------------------------------------------- /routes/callback/callback.go: -------------------------------------------------------------------------------- 1 | package callback 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net/http" 7 | "os" 8 | 9 | "github.com/coreos/go-oidc" 10 | 11 | "app" 12 | "auth" 13 | ) 14 | 15 | func CallbackHandler(w http.ResponseWriter, r *http.Request) { 16 | session, err := app.Store.Get(r, "auth-session") 17 | if err != nil { 18 | http.Error(w, err.Error(), http.StatusInternalServerError) 19 | return 20 | } 21 | 22 | if r.URL.Query().Get("state") != session.Values["state"] { 23 | http.Error(w, "Invalid state parameter", http.StatusBadRequest) 24 | return 25 | } 26 | 27 | authenticator, err := auth.NewAuthenticator() 28 | if err != nil { 29 | http.Error(w, err.Error(), http.StatusInternalServerError) 30 | return 31 | } 32 | 33 | token, err := authenticator.Config.Exchange(context.TODO(), r.URL.Query().Get("code")) 34 | if err != nil { 35 | log.Printf("no token found: %v", err) 36 | w.WriteHeader(http.StatusUnauthorized) 37 | return 38 | } 39 | 40 | rawIDToken, ok := token.Extra("id_token").(string) 41 | if !ok { 42 | http.Error(w, "No id_token field in oauth2 token.", http.StatusInternalServerError) 43 | return 44 | } 45 | 46 | oidcConfig := &oidc.Config{ 47 | ClientID: os.Getenv("clientid"), 48 | } 49 | 50 | idToken, err := authenticator.Provider.Verifier(oidcConfig).Verify(context.TODO(), rawIDToken) 51 | 52 | if err != nil { 53 | http.Error(w, "Failed to verify ID Token: "+err.Error(), http.StatusInternalServerError) 54 | return 55 | } 56 | 57 | // Getting now the userInfo 58 | var profile map[string]interface{} 59 | if err := idToken.Claims(&profile); err != nil { 60 | http.Error(w, err.Error(), http.StatusInternalServerError) 61 | return 62 | } 63 | 64 | session.Values["id_token"] = rawIDToken 65 | session.Values["access_token"] = token.AccessToken 66 | session.Values["profile"] = profile 67 | 68 | log.Print(profile) 69 | 70 | err = session.Save(r, w) 71 | 72 | if err != nil { 73 | http.Error(w, err.Error(), http.StatusInternalServerError) 74 | return 75 | } 76 | 77 | // Redirect to logged in page 78 | http.Redirect(w, r, "/user", http.StatusSeeOther) 79 | } 80 | -------------------------------------------------------------------------------- /auth/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= 3 | github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= 4 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 5 | github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= 6 | github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= 7 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 8 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0= 9 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 10 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 11 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg= 12 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 13 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= 14 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 15 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= 16 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 17 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 18 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 19 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 20 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 21 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 22 | gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4= 23 | gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= 24 | -------------------------------------------------------------------------------- /routes/login/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= 3 | github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= 4 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 5 | github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= 6 | github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= 7 | github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ= 8 | github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= 9 | github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= 10 | github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 11 | github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= 12 | github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= 13 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 14 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0= 15 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 16 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 17 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 18 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= 19 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 20 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= 21 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 22 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 23 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 24 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 25 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 26 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 27 | gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4= 28 | gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= 29 | -------------------------------------------------------------------------------- /routes/callback/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= 3 | github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= 4 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 5 | github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= 6 | github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= 7 | github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ= 8 | github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= 9 | github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= 10 | github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 11 | github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= 12 | github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= 13 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 14 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0= 15 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 16 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 17 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg= 18 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 19 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= 20 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 21 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= 22 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 23 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 24 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 25 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 26 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 27 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 28 | gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4= 29 | gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= 30 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/codegangsta/negroni v1.0.0 h1:+aYywywx4bnKXWvoWtRfJ91vC59NbEhEY03sZjQhbVY= 3 | github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= 4 | github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM= 5 | github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= 6 | github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= 7 | github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= 8 | github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= 9 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 10 | github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= 11 | github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 12 | github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= 13 | github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 14 | github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= 15 | github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 16 | github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= 17 | github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= 18 | github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ= 19 | github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= 20 | github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= 21 | github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 22 | github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= 23 | github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= 24 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 25 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0= 26 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 27 | golang.org/x/crypto v0.0.0-20200117160349-530e935923ad h1:Jh8cai0fqIK+f6nG0UgPW5wFk8wmiMhM3AyciDBdtQg= 28 | golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 29 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 30 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg= 31 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 32 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= 33 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 34 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= 35 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 36 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 37 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 38 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 39 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 40 | google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= 41 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 42 | gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4= 43 | gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= 44 | gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y= 45 | gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= 46 | --------------------------------------------------------------------------------