2019-07-31 18:34:27 -08:00
|
|
|
package webcontext
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-08-07 16:17:17 -08:00
|
|
|
|
2019-07-31 18:34:27 -08:00
|
|
|
"github.com/gorilla/sessions"
|
2019-08-07 16:17:17 -08:00
|
|
|
"github.com/pborman/uuid"
|
2019-07-31 18:34:27 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
// ctxKeySession represents the type of value for the context key.
|
|
|
|
type ctxKeySession int
|
|
|
|
|
|
|
|
// KeySession is used to store/retrieve a Session from a context.Context.
|
|
|
|
const KeySession ctxKeySession = 1
|
|
|
|
|
2019-08-04 14:48:43 -08:00
|
|
|
// Session keys used to store values.
|
|
|
|
const (
|
|
|
|
SessionKeyAccessToken = iota
|
|
|
|
)
|
2019-08-03 15:01:17 -08:00
|
|
|
|
2019-08-07 16:17:17 -08:00
|
|
|
// KeySessionID is the key used to store the ID of the session in its values.
|
|
|
|
const KeySessionID = "_sid"
|
|
|
|
|
2019-07-31 18:34:27 -08:00
|
|
|
// ContextWithSession appends a universal translator to a context.
|
|
|
|
func ContextWithSession(ctx context.Context, session *sessions.Session) context.Context {
|
|
|
|
return context.WithValue(ctx, KeySession, session)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ContextSession returns the session from a context.
|
2019-08-04 21:28:02 -08:00
|
|
|
func ContextSession(ctx context.Context) *sessions.Session {
|
|
|
|
if s, ok := ctx.Value(KeySession).(*sessions.Session); ok {
|
2019-08-07 16:17:17 -08:00
|
|
|
if sid, ok := s.Values[KeySessionID].(string); ok {
|
|
|
|
s.ID = sid
|
|
|
|
}
|
|
|
|
|
2019-08-04 14:48:43 -08:00
|
|
|
return s
|
|
|
|
}
|
|
|
|
return nil
|
2019-07-31 18:34:27 -08:00
|
|
|
}
|
|
|
|
|
2019-08-07 16:17:17 -08:00
|
|
|
// ContextAccessToken returns the JWT access token from the context session.
|
2019-07-31 18:34:27 -08:00
|
|
|
func ContextAccessToken(ctx context.Context) (string, bool) {
|
2019-08-04 21:28:02 -08:00
|
|
|
sess := ContextSession(ctx)
|
2019-08-04 14:48:43 -08:00
|
|
|
if sess == nil {
|
|
|
|
return "", false
|
|
|
|
}
|
|
|
|
if sv, ok := sess.Values[SessionKeyAccessToken].(string); ok {
|
2019-07-31 18:34:27 -08:00
|
|
|
return sv, true
|
|
|
|
}
|
|
|
|
return "", false
|
|
|
|
}
|
|
|
|
|
2019-08-07 16:17:17 -08:00
|
|
|
// SessionInit creates a new session with a valid JWT access token.
|
2019-08-04 21:28:02 -08:00
|
|
|
func SessionInit(session *sessions.Session, accessToken string) *sessions.Session {
|
2019-08-03 16:35:57 -08:00
|
|
|
|
2019-08-07 16:17:17 -08:00
|
|
|
// Always create a new session ID to ensure when session ID is being used as a cache key, logout/login
|
|
|
|
// forces any cache to be flushed.
|
|
|
|
session.ID = uuid.NewRandom().String()
|
|
|
|
|
|
|
|
// Not sure why sessions.Session has the ID prop but it is not persisted by default.
|
|
|
|
session.Values[KeySessionID] = session.ID
|
|
|
|
|
2019-08-04 21:28:02 -08:00
|
|
|
session.Values[SessionKeyAccessToken] = accessToken
|
2019-08-03 16:35:57 -08:00
|
|
|
|
2019-08-04 21:28:02 -08:00
|
|
|
return session
|
2019-07-31 18:34:27 -08:00
|
|
|
}
|
2019-08-03 16:35:57 -08:00
|
|
|
|
2019-08-07 16:17:17 -08:00
|
|
|
// SessionUpdateAccessToken updates the JWT access token stored in the session.
|
2019-08-04 21:28:02 -08:00
|
|
|
func SessionUpdateAccessToken(session *sessions.Session, accessToken string) *sessions.Session {
|
2019-08-04 14:48:43 -08:00
|
|
|
session.Values[SessionKeyAccessToken] = accessToken
|
2019-08-03 16:35:57 -08:00
|
|
|
return session
|
|
|
|
}
|
|
|
|
|
2019-08-07 16:17:17 -08:00
|
|
|
// SessionDestroy removes the access token from the session which revokes authentication for the user.
|
2019-08-04 21:28:02 -08:00
|
|
|
func SessionDestroy(session *sessions.Session) *sessions.Session {
|
2019-08-04 14:48:43 -08:00
|
|
|
|
|
|
|
delete(session.Values, SessionKeyAccessToken)
|
|
|
|
|
|
|
|
return session
|
|
|
|
}
|