Skip to content

Commit d8b5483

Browse files
backend: Add helper functions for handling OIDC Callback
Signed-off-by: SinghaAnirban005 <[email protected]>
1 parent b87bc25 commit d8b5483

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

backend/cmd/headlamp.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,104 @@ func handleOIDCCallback(
565565
processOIDCCallback(config, w, r, oauthConfig, state)
566566
}
567567

568+
func writeOIDCError(w http.ResponseWriter, err error, msg string) {
569+
if err != nil {
570+
msg = fmt.Sprintf("%s: %v", msg, err)
571+
}
572+
573+
http.Error(w, msg, http.StatusBadRequest)
574+
}
575+
576+
func validateState(state string) error {
577+
if _, err := base64.StdEncoding.DecodeString(state); err != nil {
578+
return fmt.Errorf("failed to decode state: %w", err)
579+
}
580+
581+
return nil
582+
}
583+
584+
func getOAuthConfigFromState(
585+
state string,
586+
oauthRequestMap map[string]*OauthConfig,
587+
) *OauthConfig {
588+
return oauthRequestMap[state]
589+
}
590+
591+
func processOIDCCallback(
592+
config *HeadlampConfig,
593+
w http.ResponseWriter,
594+
r *http.Request,
595+
oauthConfig *OauthConfig,
596+
state string,
597+
) {
598+
token, err := exchangeCode(oauthConfig, r)
599+
if err != nil {
600+
writeOIDCError(w, err, "failed to exchange token")
601+
return
602+
}
603+
604+
tokenType := "id_token"
605+
if config.oidcUseAccessToken {
606+
tokenType = "access_token"
607+
}
608+
609+
rawToken := getRawToken(token, tokenType)
610+
if rawToken == "" {
611+
writeOIDCError(w, nil, fmt.Sprintf("no %s field", tokenType))
612+
return
613+
}
614+
615+
cacheToken(config.cache, rawToken, token.RefreshToken)
616+
verifyToken(oauthConfig, rawToken)
617+
redirectUser(config, w, r, state, rawToken)
618+
}
619+
620+
func exchangeCode(oauthConfig *OauthConfig, r *http.Request) (*oauth2.Token, error) {
621+
return oauthConfig.Config.Exchange(oauthConfig.Ctx, r.URL.Query().Get("code"))
622+
}
623+
624+
func getRawToken(token *oauth2.Token, tokenType string) string {
625+
rawToken, _ := token.Extra(tokenType).(string)
626+
return rawToken
627+
}
628+
629+
func cacheToken(cache cache.Cache[interface{}], rawToken, refreshToken string) {
630+
_ = cache.Set(context.Background(),
631+
fmt.Sprintf("oidc-token-%s", rawToken),
632+
refreshToken)
633+
}
634+
635+
func verifyToken(oauthConfig *OauthConfig, rawToken string) {
636+
_, _ = oauthConfig.Verifier.Verify(oauthConfig.Ctx, rawToken)
637+
}
638+
639+
func redirectUser(
640+
config *HeadlampConfig,
641+
w http.ResponseWriter,
642+
r *http.Request,
643+
state,
644+
rawToken string,
645+
) {
646+
redirectURL := buildRedirectURL(config, state, rawToken)
647+
http.Redirect(w, r, redirectURL, http.StatusSeeOther)
648+
}
649+
650+
func buildRedirectURL(config *HeadlampConfig, state, rawToken string) string {
651+
base := "http://localhost:3000/"
652+
if !config.DevMode {
653+
base = "/"
654+
}
655+
656+
if trimmed := strings.Trim(config.BaseURL, "/"); trimmed != "" {
657+
base += trimmed + "/"
658+
}
659+
660+
decodedState, _ := base64.StdEncoding.DecodeString(state)
661+
662+
return fmt.Sprintf("%sauth?cluster=%s&token=%s",
663+
base, decodedState, rawToken)
664+
}
665+
568666
func handleOIDC(
569667
config *HeadlampConfig,
570668
w http.ResponseWriter,

0 commit comments

Comments
 (0)