mirror of https://github.com/dexidp/dex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
3.1 KiB
100 lines
3.1 KiB
package server |
|
|
|
import ( |
|
"net/http" |
|
"net/url" |
|
"time" |
|
|
|
"github.com/coreos/dex/pkg/log" |
|
"github.com/coreos/dex/user" |
|
"github.com/coreos/dex/user/manager" |
|
"github.com/coreos/go-oidc/jose" |
|
"github.com/coreos/go-oidc/key" |
|
) |
|
|
|
type invitationTemplateData struct { |
|
Error, Message string |
|
} |
|
|
|
type InvitationHandler struct { |
|
issuerURL url.URL |
|
passwordResetURL url.URL |
|
um *manager.UserManager |
|
keysFunc func() ([]key.PublicKey, error) |
|
signerFunc func() (jose.Signer, error) |
|
redirectValidityWindow time.Duration |
|
} |
|
|
|
func (h *InvitationHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
switch r.Method { |
|
case "GET": |
|
h.handleGET(w, r) |
|
default: |
|
writeAPIError(w, http.StatusMethodNotAllowed, newAPIError(errorInvalidRequest, |
|
"method not allowed")) |
|
} |
|
} |
|
|
|
func (h *InvitationHandler) handleGET(w http.ResponseWriter, r *http.Request) { |
|
q := r.URL.Query() |
|
token := q.Get("token") |
|
|
|
keys, err := h.keysFunc() |
|
if err != nil { |
|
log.Errorf("internal error getting public keys: %v", err) |
|
writeAPIError(w, http.StatusInternalServerError, newAPIError(errorServerError, |
|
"There's been an error processing your request.")) |
|
return |
|
} |
|
|
|
invite, err := user.ParseAndVerifyInvitationToken(token, h.issuerURL, keys) |
|
if err != nil { |
|
log.Debugf("invalid invitation token: %v (%v)", err, token) |
|
writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidRequest, |
|
"Your invitation could not be verified")) |
|
return |
|
} |
|
|
|
_, err = h.um.VerifyEmail(invite) |
|
if err != nil && err != manager.ErrorEmailAlreadyVerified { |
|
// Allow AlreadyVerified folks to pass through- otherwise |
|
// folks who encounter an error after passing this point will |
|
// never be able to set their passwords. |
|
log.Debugf("error attempting to verify email: %v", err) |
|
switch err { |
|
case user.ErrorNotFound: |
|
writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidRequest, |
|
"Your email does not match the email address on file")) |
|
return |
|
default: |
|
log.Errorf("internal error verifying email: %v", err) |
|
writeAPIError(w, http.StatusInternalServerError, newAPIError(errorServerError, |
|
"There's been an error processing your request.")) |
|
return |
|
} |
|
} |
|
|
|
passwordReset := invite.PasswordReset(h.issuerURL, h.redirectValidityWindow) |
|
signer, err := h.signerFunc() |
|
if err != nil || signer == nil { |
|
log.Errorf("error getting signer: %v (signer: %v)", err, signer) |
|
writeAPIError(w, http.StatusInternalServerError, newAPIError(errorServerError, |
|
"There's been an error processing your request.")) |
|
return |
|
} |
|
|
|
jwt, err := jose.NewSignedJWT(passwordReset.Claims, signer) |
|
if err != nil { |
|
log.Errorf("error constructing or signing PasswordReset from Invitation JWT: %v", err) |
|
writeAPIError(w, http.StatusInternalServerError, newAPIError(errorServerError, |
|
"There's been an error processing your request.")) |
|
return |
|
} |
|
passwordResetToken := jwt.Encode() |
|
|
|
passwordResetURL := h.passwordResetURL |
|
newQuery := passwordResetURL.Query() |
|
newQuery.Set("token", passwordResetToken) |
|
passwordResetURL.RawQuery = newQuery.Encode() |
|
http.Redirect(w, r, passwordResetURL.String(), http.StatusSeeOther) |
|
}
|
|
|