server: support out-of-band auth flow
When "urn:ietf:wg:oauth:2.0:oob" is used as a redirect URI, redirect to an internal dex page where the user is shown the code and instructed to paste it into their app.
This commit is contained in:
parent
42cd59aef4
commit
b80dbc8975
4 changed files with 66 additions and 30 deletions
|
@ -299,35 +299,23 @@ func getTemplates(issuerName, issuerLogoURL string,
|
|||
}
|
||||
|
||||
func setTemplates(srv *Server, tpls *template.Template) error {
|
||||
ltpl, err := findTemplate(LoginPageTemplateName, tpls)
|
||||
if err != nil {
|
||||
return err
|
||||
for _, t := range []struct {
|
||||
templateName string
|
||||
templatePtr **template.Template
|
||||
}{
|
||||
{LoginPageTemplateName, &srv.LoginTemplate},
|
||||
{RegisterTemplateName, &srv.RegisterTemplate},
|
||||
{VerifyEmailTemplateName, &srv.VerifyEmailTemplate},
|
||||
{SendResetPasswordEmailTemplateName, &srv.SendResetPasswordEmailTemplate},
|
||||
{ResetPasswordTemplateName, &srv.ResetPasswordTemplate},
|
||||
{OOBTemplateName, &srv.OOBTemplate},
|
||||
} {
|
||||
tpl, err := findTemplate(t.templateName, tpls)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*t.templatePtr = tpl
|
||||
}
|
||||
srv.LoginTemplate = ltpl
|
||||
|
||||
rtpl, err := findTemplate(RegisterTemplateName, tpls)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv.RegisterTemplate = rtpl
|
||||
|
||||
vtpl, err := findTemplate(VerifyEmailTemplateName, tpls)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv.VerifyEmailTemplate = vtpl
|
||||
|
||||
srtpl, err := findTemplate(SendResetPasswordEmailTemplateName, tpls)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv.SendResetPasswordEmailTemplate = srtpl
|
||||
|
||||
rpwtpl, err := findTemplate(ResetPasswordTemplateName, tpls)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv.ResetPasswordTemplate = rpwtpl
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ var (
|
|||
httpPathAcceptInvitation = "/accept-invitation"
|
||||
httpPathDebugVars = "/debug/vars"
|
||||
httpPathClientRegistration = "/registration"
|
||||
httpPathOOB = "/oob"
|
||||
|
||||
cookieLastSeen = "LastSeen"
|
||||
cookieShowEmailVerifiedMessage = "ShowEmailVerifiedMessage"
|
||||
|
@ -548,6 +549,37 @@ func handleTokenFunc(srv OIDCServer) http.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func handleOOBFunc(s *Server, tpl *template.Template) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "GET" {
|
||||
w.Header().Set("Allow", "GET")
|
||||
phttp.WriteError(w, http.StatusMethodNotAllowed, "GET only acceptable method")
|
||||
return
|
||||
}
|
||||
|
||||
key := r.URL.Query().Get("code")
|
||||
if key == "" {
|
||||
phttp.WriteError(w, http.StatusBadRequest, "Invalid Session")
|
||||
return
|
||||
}
|
||||
sessionID, err := s.SessionManager.ExchangeKey(key)
|
||||
if err != nil {
|
||||
phttp.WriteError(w, http.StatusBadRequest, "Invalid Session")
|
||||
return
|
||||
}
|
||||
code, err := s.SessionManager.NewSessionKey(sessionID)
|
||||
if err != nil {
|
||||
log.Errorf("problem getting NewSessionKey: %v", err)
|
||||
phttp.WriteError(w, http.StatusInternalServerError, "Internal Server Error")
|
||||
return
|
||||
}
|
||||
|
||||
execTemplate(w, tpl, map[string]string{
|
||||
"code": code,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func makeHealthHandler(checks []health.Checkable) http.Handler {
|
||||
return health.Checker{
|
||||
Checks: checks,
|
||||
|
|
|
@ -38,8 +38,8 @@ const (
|
|||
VerifyEmailTemplateName = "verify-email.html"
|
||||
SendResetPasswordEmailTemplateName = "send-reset-password.html"
|
||||
ResetPasswordTemplateName = "reset-password.html"
|
||||
|
||||
APIVersion = "v1"
|
||||
OOBTemplateName = "oob-template.html"
|
||||
APIVersion = "v1"
|
||||
)
|
||||
|
||||
type OIDCServer interface {
|
||||
|
@ -72,6 +72,7 @@ type Server struct {
|
|||
VerifyEmailTemplate *template.Template
|
||||
SendResetPasswordEmailTemplate *template.Template
|
||||
ResetPasswordTemplate *template.Template
|
||||
OOBTemplate *template.Template
|
||||
|
||||
HealthChecks []health.Checkable
|
||||
Connectors []connector.Connector
|
||||
|
@ -214,6 +215,7 @@ func (s *Server) HTTPHandler() http.Handler {
|
|||
mux := http.NewServeMux()
|
||||
mux.HandleFunc(httpPathDiscovery, handleDiscoveryFunc(s.ProviderConfig()))
|
||||
mux.HandleFunc(httpPathAuth, handleAuthFunc(s, s.Connectors, s.LoginTemplate, s.EnableRegistration))
|
||||
mux.HandleFunc(httpPathOOB, handleOOBFunc(s, s.OOBTemplate))
|
||||
mux.HandleFunc(httpPathToken, handleTokenFunc(s))
|
||||
mux.HandleFunc(httpPathKeys, handleKeysFunc(s.KeyManager, clock))
|
||||
mux.Handle(httpPathHealth, makeHealthHandler(checks))
|
||||
|
@ -399,6 +401,9 @@ func (s *Server) Login(ident oidc.Identity, key string) (string, error) {
|
|||
}
|
||||
|
||||
ru := ses.RedirectURL
|
||||
if ru.String() == client.OOBRedirectURI {
|
||||
ru = s.absURL(httpPathOOB)
|
||||
}
|
||||
q := ru.Query()
|
||||
q.Set("code", code)
|
||||
q.Set("state", ses.ClientState)
|
||||
|
|
11
static/html/oob-template.html
Normal file
11
static/html/oob-template.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{{ template "header.html" }}
|
||||
|
||||
<div class="panel">
|
||||
<h2 class="heading">Login Successful</h2>
|
||||
|
||||
Please copy this code, switch to your application and paste it there:
|
||||
<br/>
|
||||
<input type="text" value="{{ .code }}" />
|
||||
</div>
|
||||
|
||||
{{ template "footer.html" }}
|
Reference in a new issue