auth

Paddy 2015-05-15 Parent:0ff23f3a4ede Child:bdb83e88e1da

168:581c60f8dd23 Go to Latest

auth/authd/server.go

Switch to a JWT approach. We're going to use a JWT as our access tokens (as discussed in &yet's excellent post https://blog.andyet.com/2015/05/12/micro-services-user-info-and-auth and my ensuing conversation with Fritzy). The benefit of this approach is that we can do authentication and even some authorization without touching the database at all. The drawback is that we can no longer revoke access tokens, only the refresh tokens that grant the access tokens. We need a new config variable to set our private key, used to sign the JWT. We get to remove our token handlers, as we no longer can revoke tokens, so there's no purpose in getting information about it or listing them. Our tokenStore revokeToken gets to be simplified, as it will only ever be used for refresh tokens now. We also updated our postgres and memstore implementations. We added a helper method for generating the signed "access token" (our JWT) and started using it in the places where we're creating a Token. We get to remove the `revoked` SQL column for the tokens table, and rename the `refresh_revoked` column to just be `revoked`. We shortened our access token expiration to 15 minutes instead of an hour, to deal with the token not being revokable.

History
paddy@100 1 package main
paddy@100 2
paddy@100 3 import (
paddy@100 4 "html/template"
paddy@100 5 "log"
paddy@100 6 "net/http"
paddy@157 7 "os"
paddy@100 8
paddy@107 9 "code.secondbit.org/auth.hg"
paddy@100 10 "github.com/gorilla/mux"
paddy@100 11 )
paddy@100 12
paddy@100 13 func main() {
paddy@151 14 log.SetFlags(log.LstdFlags | log.Llongfile)
paddy@157 15 var config auth.Config
paddy@157 16 if os.Getenv("AUTH_PG_DB") != "" {
paddy@157 17 p, err := auth.NewPostgres(os.Getenv("AUTH_PG_DB"))
paddy@157 18 if err != nil {
paddy@157 19 panic(err)
paddy@157 20 }
paddy@157 21 config.ClientStore = &p
paddy@157 22 config.AuthCodeStore = &p
paddy@157 23 config.ProfileStore = &p
paddy@157 24 config.TokenStore = &p
paddy@157 25 config.SessionStore = &p
paddy@157 26 config.ScopeStore = &p
paddy@157 27 } else {
paddy@157 28 store := auth.NewMemstore()
paddy@157 29 config.ClientStore = store
paddy@157 30 config.AuthCodeStore = store
paddy@157 31 config.ProfileStore = store
paddy@157 32 config.TokenStore = store
paddy@157 33 config.SessionStore = store
paddy@157 34 config.ScopeStore = store
paddy@149 35 }
paddy@157 36 config.Template = template.Must(template.New("base").ParseGlob("./templates/*.gotmpl"))
paddy@157 37 config.LoginURI = "/login"
paddy@168 38 config.JWTPrivateKey = []byte(`secret`)
paddy@157 39 err := config.Init()
paddy@106 40 if err != nil {
paddy@106 41 log.Fatal(err)
paddy@106 42 }
paddy@100 43 context, err := auth.NewContext(config)
paddy@100 44 if err != nil {
paddy@100 45 panic(err)
paddy@100 46 }
paddy@149 47 err = context.CreateScopes([]auth.Scope{
paddy@149 48 {ID: "testscope", Name: "Test Scope"},
paddy@149 49 })
paddy@157 50 if err != nil && err != auth.ErrScopeAlreadyExists {
paddy@157 51 log.Fatal(err)
paddy@152 52 }
paddy@100 53
paddy@100 54 router := mux.NewRouter()
paddy@100 55 auth.RegisterOAuth2(router, context)
paddy@100 56 auth.RegisterSessionHandlers(router, context)
paddy@106 57 auth.RegisterProfileHandlers(router, context)
paddy@108 58 auth.RegisterClientHandlers(router, context)
paddy@100 59 http.Handle("/", router)
paddy@100 60 log.Fatal(http.ListenAndServe(":8080", nil))
paddy@100 61 }