harness-drone/server/session/session.go

114 lines
2.7 KiB
Go
Raw Normal View History

2015-04-08 22:43:59 +00:00
package session
import (
"fmt"
"net/http"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/drone/drone/common"
"github.com/drone/drone/settings"
"github.com/gorilla/securecookie"
)
type Session interface {
2015-04-13 06:15:28 +00:00
GenerateToken(*common.Token) (string, error)
GetLogin(*http.Request) *common.Token
2015-04-08 22:43:59 +00:00
}
type session struct {
secret []byte
expire time.Duration
}
func New(s *settings.Session) Session {
2015-04-08 23:36:56 +00:00
// TODO (bradrydzewski) hook up the Session.Expires
secret := []byte(s.Secret)
2015-04-08 22:43:59 +00:00
expire := time.Hour * 72
2015-04-08 23:36:56 +00:00
if len(secret) == 0 {
securecookie.GenerateRandomKey(32)
}
2015-04-08 22:43:59 +00:00
return &session{
secret: secret,
expire: expire,
}
}
// GenerateToken generates a JWT token for the user session
// that can be appended to the #access_token segment to
// facilitate client-based OAuth2.
2015-04-13 06:15:28 +00:00
func (s *session) GenerateToken(t *common.Token) (string, error) {
2015-04-08 22:43:59 +00:00
token := jwt.New(jwt.GetSigningMethod("HS256"))
2015-04-13 05:32:32 +00:00
token.Claims["user"] = t.Login
token.Claims["kind"] = t.Kind
token.Claims["date"] = t.Issued
token.Claims["label"] = t.Label
2015-04-08 22:43:59 +00:00
return token.SignedString(s.secret)
}
// GetLogin gets the currently authenticated user for the
// http.Request. The user details will be stored as either
// a simple API token or JWT bearer token.
func (s *session) GetLogin(r *http.Request) *common.Token {
t := getToken(r)
if len(t) == 0 {
return nil
2015-04-08 22:43:59 +00:00
}
claims := getClaims(t, s.secret)
2015-04-13 05:32:32 +00:00
if claims == nil || claims["user"] == nil || claims["date"] == nil || claims["label"] == nil || claims["kind"] == nil {
return nil
2015-04-08 22:43:59 +00:00
}
2015-04-14 02:07:05 +00:00
token := &common.Token{
2015-04-13 05:32:32 +00:00
Kind: claims["kind"].(string),
Login: claims["user"].(string),
Label: claims["label"].(string),
Issued: int64(claims["date"].(float64)),
}
2015-04-14 02:07:05 +00:00
if token.Kind != common.TokenSess {
return token
}
2015-04-14 02:11:33 +00:00
if time.Unix(token.Issued, 0).Add(s.expire).Before(time.Now()) {
2015-04-14 02:07:05 +00:00
return nil
}
return token
2015-04-08 22:43:59 +00:00
}
// getToken is a helper function that extracts the token
// from the http.Request.
func getToken(r *http.Request) string {
token := getTokenHeader(r)
if len(token) == 0 {
token = getTokenParam(r)
}
return token
}
// getTokenHeader parses the JWT token value from
// the http Authorization header.
func getTokenHeader(r *http.Request) string {
var tokenstr = r.Header.Get("Authorization")
fmt.Sscanf(tokenstr, "Bearer %s", &tokenstr)
return tokenstr
}
// getTokenParam parses the JWT token value from
// the http Request's query parameter.
func getTokenParam(r *http.Request) string {
return r.FormValue("access_token")
}
// getClaims is a helper function that extracts the token
// claims from the JWT token string.
func getClaims(token string, secret []byte) map[string]interface{} {
t, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
return secret, nil
})
if err != nil || !t.Valid {
return nil
}
return t.Claims
}