forked from RichardKnop/go-oauth2-server
-
Notifications
You must be signed in to change notification settings - Fork 0
/
service.go
139 lines (119 loc) · 3.45 KB
/
service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package session
import (
"encoding/gob"
"errors"
"net/http"
"github.com/RichardKnop/go-oauth2-server/config"
"github.com/gorilla/sessions"
)
// Service wraps session functionality
type Service struct {
sessionStore sessions.Store
sessionOptions *sessions.Options
session *sessions.Session
r *http.Request
w http.ResponseWriter
}
// UserSession has user data stored in a session after logging in
type UserSession struct {
ClientID string
Username string
AccessToken string
RefreshToken string
}
var (
// StorageSessionName ...
StorageSessionName = "go_oauth2_server_session"
// UserSessionKey ...
UserSessionKey = "go_oauth2_server_user"
// ErrSessonNotStarted ...
ErrSessonNotStarted = errors.New("Session not started")
)
func init() {
// Register a new datatype for storage in sessions
gob.Register(new(UserSession))
}
// NewService starts a new Service instance
func NewService(cnf *config.Config, r *http.Request, w http.ResponseWriter) *Service {
return &Service{
// Session cookie storage
sessionStore: sessions.NewCookieStore([]byte(cnf.Session.Secret)),
// Session options
sessionOptions: &sessions.Options{
Path: cnf.Session.Path,
MaxAge: cnf.Session.MaxAge,
HttpOnly: cnf.Session.HTTPOnly,
},
r: r,
w: w,
}
}
// StartSession starts a new session. This method must be called before other
// public methods of this struct as it sets the internal session object
func (s *Service) StartSession() error {
session, err := s.sessionStore.Get(s.r, StorageSessionName)
if err != nil {
return err
}
s.session = session
return nil
}
// GetUserSession returns the user session
func (s *Service) GetUserSession() (*UserSession, error) {
// Make sure StartSession has been called
if s.session == nil {
return nil, ErrSessonNotStarted
}
// Retrieve our user session struct and type-assert it
userSession, ok := s.session.Values[UserSessionKey].(*UserSession)
if !ok {
return nil, errors.New("User session type assertion error")
}
return userSession, nil
}
// SetUserSession saves the user session
func (s *Service) SetUserSession(userSession *UserSession) error {
// Make sure StartSession has been called
if s.session == nil {
return ErrSessonNotStarted
}
// Set a new user session
s.session.Values[UserSessionKey] = userSession
return s.session.Save(s.r, s.w)
}
// ClearUserSession deletes the user session
func (s *Service) ClearUserSession() error {
// Make sure StartSession has been called
if s.session == nil {
return ErrSessonNotStarted
}
// Delete the user session
delete(s.session.Values, UserSessionKey)
return s.session.Save(s.r, s.w)
}
// SetFlashMessage sets a flash message,
// useful for displaying an error after 302 redirection
func (s *Service) SetFlashMessage(msg string) error {
// Make sure StartSession has been called
if s.session == nil {
return ErrSessonNotStarted
}
// Add the flash message
s.session.AddFlash(msg)
return s.session.Save(s.r, s.w)
}
// GetFlashMessage returns the first flash message
func (s *Service) GetFlashMessage() (interface{}, error) {
// Make sure StartSession has been called
if s.session == nil {
return nil, ErrSessonNotStarted
}
// Get the last flash message from the stack
if flashes := s.session.Flashes(); len(flashes) > 0 {
// We need to save the session, otherwise the flash message won't be removed
s.session.Save(s.r, s.w)
return flashes[0], nil
}
// No flash messages in the stack
return nil, nil
}