super-graph/serv/auth_rails.go

187 lines
3.9 KiB
Go
Raw Permalink Normal View History

2019-03-24 14:57:29 +01:00
package serv
import (
"context"
"errors"
"fmt"
"net/http"
"net/url"
"strings"
2019-03-24 14:57:29 +01:00
"github.com/bradfitz/gomemcache/memcache"
"github.com/dosco/super-graph/rails"
2019-03-24 14:57:29 +01:00
"github.com/garyburd/redigo/redis"
)
func railsHandler(authc configAuth, next http.Handler) http.HandlerFunc {
ru := authc.Rails.URL
if strings.HasPrefix(ru, "memcache:") {
return railsMemcacheHandler(authc, next)
}
if strings.HasPrefix(ru, "redis:") {
return railsRedisHandler(authc, next)
}
return railsCookieHandler(authc, next)
}
func railsRedisHandler(authc configAuth, next http.Handler) http.HandlerFunc {
cookie := authc.Cookie
2019-03-24 14:57:29 +01:00
if len(cookie) == 0 {
2019-11-25 08:22:33 +01:00
errlog.Fatal().Msg("no auth.cookie defined")
2019-03-24 14:57:29 +01:00
}
if len(authc.Rails.URL) == 0 {
2019-11-25 08:22:33 +01:00
errlog.Fatal().Msg("no auth.rails.url defined")
2019-03-24 14:57:29 +01:00
}
rp := &redis.Pool{
MaxIdle: authc.Rails.MaxIdle,
MaxActive: authc.Rails.MaxActive,
2019-03-24 14:57:29 +01:00
Dial: func() (redis.Conn, error) {
c, err := redis.DialURL(authc.Rails.URL)
2019-03-24 14:57:29 +01:00
if err != nil {
2019-11-25 08:22:33 +01:00
errlog.Fatal().Err(err).Send()
2019-03-24 14:57:29 +01:00
}
pwd := authc.Rails.Password
2019-03-24 14:57:29 +01:00
if len(pwd) != 0 {
if _, err := c.Do("AUTH", pwd); err != nil {
2019-11-25 08:22:33 +01:00
errlog.Fatal().Err(err).Send()
2019-03-24 14:57:29 +01:00
}
}
return c, err
},
}
return func(w http.ResponseWriter, r *http.Request) {
ck, err := r.Cookie(cookie)
if err != nil {
next.ServeHTTP(w, r)
return
}
key := fmt.Sprintf("session:%s", ck.Value)
sessionData, err := redis.Bytes(rp.Get().Do("GET", key))
if err != nil {
next.ServeHTTP(w, r)
return
}
userID, err := rails.ParseCookie(string(sessionData))
2019-03-24 14:57:29 +01:00
if err != nil {
next.ServeHTTP(w, r)
return
}
ctx := context.WithValue(r.Context(), userIDKey, userID)
next.ServeHTTP(w, r.WithContext(ctx))
}
}
func railsMemcacheHandler(authc configAuth, next http.Handler) http.HandlerFunc {
cookie := authc.Cookie
2019-03-24 14:57:29 +01:00
if len(cookie) == 0 {
2019-11-25 08:22:33 +01:00
errlog.Fatal().Msg("no auth.cookie defined")
2019-03-24 14:57:29 +01:00
}
if len(authc.Rails.URL) == 0 {
2019-11-25 08:22:33 +01:00
errlog.Fatal().Msg("no auth.rails.url defined")
}
rURL, err := url.Parse(authc.Rails.URL)
if err != nil {
2019-11-25 08:22:33 +01:00
errlog.Fatal().Err(err).Send()
2019-03-24 14:57:29 +01:00
}
mc := memcache.New(rURL.Host)
2019-03-24 14:57:29 +01:00
return func(w http.ResponseWriter, r *http.Request) {
ck, err := r.Cookie(cookie)
if err != nil {
next.ServeHTTP(w, r)
return
}
key := fmt.Sprintf("session:%s", ck.Value)
item, err := mc.Get(key)
if err != nil {
next.ServeHTTP(w, r)
return
}
userID, err := rails.ParseCookie(string(item.Value))
2019-03-24 14:57:29 +01:00
if err != nil {
next.ServeHTTP(w, r)
return
}
ctx := context.WithValue(r.Context(), userIDKey, userID)
next.ServeHTTP(w, r.WithContext(ctx))
}
}
func railsCookieHandler(authc configAuth, next http.Handler) http.HandlerFunc {
cookie := authc.Cookie
2019-03-24 14:57:29 +01:00
if len(cookie) == 0 {
2019-11-25 08:22:33 +01:00
errlog.Fatal().Msg("no auth.cookie defined")
2019-03-24 14:57:29 +01:00
}
ra, err := railsAuth(authc)
if err != nil {
2019-11-25 08:22:33 +01:00
errlog.Fatal().Err(err).Send()
2019-03-24 14:57:29 +01:00
}
2019-03-24 14:57:29 +01:00
return func(w http.ResponseWriter, r *http.Request) {
ck, err := r.Cookie(cookie)
if err != nil || len(ck.Value) == 0 {
logger.Warn().Err(err).Msg("rails cookie missing")
2019-03-24 14:57:29 +01:00
next.ServeHTTP(w, r)
return
}
userID, err := ra.ParseCookie(ck.Value)
2019-03-24 14:57:29 +01:00
if err != nil {
logger.Warn().Err(err).Msg("failed to parse rails cookie")
2019-03-24 14:57:29 +01:00
next.ServeHTTP(w, r)
return
}
ctx := context.WithValue(r.Context(), userIDKey, userID)
next.ServeHTTP(w, r.WithContext(ctx))
}
}
func railsAuth(authc configAuth) (*rails.Auth, error) {
secret := authc.Rails.SecretKeyBase
if len(secret) == 0 {
return nil, errors.New("no auth.rails.secret_key_base defined")
2019-03-24 14:57:29 +01:00
}
version := authc.Rails.Version
if len(version) == 0 {
return nil, errors.New("no auth.rails.version defined")
2019-03-24 14:57:29 +01:00
}
ra, err := rails.NewAuth(version, secret)
2019-03-24 14:57:29 +01:00
if err != nil {
return nil, err
2019-03-24 14:57:29 +01:00
}
if len(authc.Rails.Salt) != 0 {
ra.Salt = authc.Rails.Salt
2019-03-24 14:57:29 +01:00
}
if len(authc.Rails.SignSalt) != 0 {
ra.SignSalt = authc.Rails.SignSalt
2019-03-24 14:57:29 +01:00
}
if len(authc.Rails.AuthSalt) != 0 {
ra.AuthSalt = authc.Rails.AuthSalt
2019-03-24 14:57:29 +01:00
}
return ra, nil
2019-03-24 14:57:29 +01:00
}