forked from i-love-flamingo/flamingo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
callback_controller.go
120 lines (106 loc) · 3.71 KB
/
callback_controller.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
package interfaces
import (
"context"
"flamingo.me/flamingo/core/auth/application"
"flamingo.me/flamingo/core/auth/domain"
"flamingo.me/flamingo/framework/config"
"flamingo.me/flamingo/framework/flamingo"
"flamingo.me/flamingo/framework/web"
"flamingo.me/flamingo/framework/web/responder"
"github.com/pkg/errors"
)
type (
CallbackControllerInterface interface {
Get(context.Context, *web.Request) web.Response
}
// CallbackController handles the oauth2.0 callback
CallbackController struct {
responder.RedirectAware
responder.ErrorAware
authManager *application.AuthManager
logger flamingo.Logger
eventPublisher *application.EventPublisher
tokenExtras config.Slice
userService application.UserServiceInterface
}
)
// Inject CallbackController dependencies
func (cc *CallbackController) Inject(
redirectAware responder.RedirectAware,
errorAware responder.ErrorAware,
authManager *application.AuthManager,
logger flamingo.Logger,
eventPublisher *application.EventPublisher,
userService application.UserServiceInterface,
cfg *struct {
TokenExtras config.Slice `inject:"config:auth.tokenExtras"`
},
) {
cc.RedirectAware = redirectAware
cc.ErrorAware = errorAware
cc.authManager = authManager
cc.logger = logger
cc.eventPublisher = eventPublisher
cc.tokenExtras = cfg.TokenExtras
cc.userService = userService
}
// Get handler for callbacks
func (cc *CallbackController) Get(c context.Context, request *web.Request) web.Response {
// Verify state and errors.
defer request.Session().Delete(application.KeyAuthstate)
if request.Session().Try(application.KeyAuthstate) != request.MustQuery1("state") {
cc.logger.Error("Invalid State", request.Session().Try(application.KeyAuthstate), request.MustQuery1("state"))
return cc.Error(c, errors.New("Invalid State"))
}
code, cOk := request.Query1("code")
errCode, eOk := request.Query1("error")
if !cOk && !eOk {
err := errors.New("missing both code and error get parameter")
cc.logger.Error("core.auth.callback Missing parameter", err)
return cc.Error(c, errors.WithStack(err))
} else if cOk {
oauth2Token, err := cc.authManager.OAuth2Config(c).Exchange(c, code)
if err != nil {
cc.logger.Error("core.auth.callback Error OAuth2Config Exchange", err)
return cc.Error(c, errors.WithStack(err))
}
var extras []string
err = cc.tokenExtras.MapInto(&extras)
if err != nil {
panic(err)
}
tokenExtras := &domain.TokenExtras{}
for _, extra := range extras {
value := oauth2Token.Extra(extra)
parsed, ok := value.(string)
if !ok {
cc.logger.Error("core.auth.callback invalid type for extras", value)
continue
}
tokenExtras.Add(extra, parsed)
}
request.Session().Store(application.KeyToken, oauth2Token)
rawToken, err := cc.authManager.ExtractRawIDToken(oauth2Token)
request.Session().Store(application.KeyRawIDToken, rawToken)
request.Session().Store(application.KeyTokenExtras, tokenExtras)
if err != nil {
cc.logger.Error("core.auth.callback Error ExtractRawIDToken", err)
return cc.Error(c, errors.WithStack(err))
}
err = cc.userService.InitUser(c, request.Session().G())
if err != nil {
cc.logger.Error("core.auth.callback Error init user", err)
return cc.Error(c, errors.WithStack(err))
}
cc.eventPublisher.PublishLoginEvent(c, &domain.LoginEvent{Session: request.Session().G()})
cc.logger.Debug("successful logged in and saved tokens", oauth2Token)
request.Session().AddFlash("successful logged in", "info")
} else if eOk {
cc.logger.Error("core.auth.callback Error parameter", errCode)
}
if redirect, ok := request.Session().Load("auth.redirect"); ok {
request.Session().Delete("auth.redirect")
return cc.RedirectURL(redirect.(string))
}
return cc.Redirect("home", nil)
}