4444 ErrInvalidClient = errors .New ("invalid_client" )
4545)
4646
47+ type OIDCPrompt string
48+
49+ const (
50+ OIDCPromptLogin OIDCPrompt = "login"
51+ OIDCPromptNone OIDCPrompt = "none"
52+ )
53+
54+ var SupportedPrompts = []string {string (OIDCPromptLogin ), string (OIDCPromptNone )}
55+
4756// This is not spec-compliant, the ID token SHOULD NOT contain user info claims but,
4857// it has became a "standard" and apps are looking for the claims in the ID tokens
4958// instead of calling the userinfo endpoint, so we include them in the ID token as well
@@ -54,6 +63,7 @@ type ClaimSet struct {
5463 Sub string `json:"sub"`
5564 Iat int64 `json:"iat"`
5665 Exp int64 `json:"exp"`
66+ AuthTime int64 `json:"auth_time,omitempty"`
5767 Name string `json:"name,omitempty"`
5868 GivenName string `json:"given_name,omitempty"`
5969 FamilyName string `json:"family_name,omitempty"`
@@ -117,6 +127,7 @@ type AuthorizeRequest struct {
117127 Nonce string `form:"nonce" json:"nonce" url:"nonce"`
118128 CodeChallenge string `form:"code_challenge" json:"code_challenge" url:"code_challenge"`
119129 CodeChallengeMethod string `form:"code_challenge_method" json:"code_challenge_method" url:"code_challenge_method"`
130+ Prompt string `form:"prompt" json:"prompt" url:"prompt"`
120131}
121132
122133type AuthorizeCodeEntry struct {
@@ -127,6 +138,7 @@ type AuthorizeCodeEntry struct {
127138 Nonce string
128139 CodeChallenge string
129140 Userinfo UserinfoResponse
141+ AuthTime int64
130142}
131143
132144type UsedCodeEntry struct {
@@ -423,6 +435,7 @@ func (service *OIDCService) CreateCode(req AuthorizeRequest, userContext model.U
423435 ClientID : req .ClientID ,
424436 Nonce : req .Nonce ,
425437 Userinfo : service .userinfoFromContext (userContext , sub ),
438+ AuthTime : userContext .AuthTime ,
426439 }
427440
428441 if req .CodeChallenge != "" {
@@ -512,7 +525,7 @@ func (service *OIDCService) GetCodeEntry(codeHash string, clientId string) (*Aut
512525 return & entry , true
513526}
514527
515- func (service * OIDCService ) generateIDToken (client model.OIDCClientConfig , user UserinfoResponse , scope string , nonce string ) (string , error ) {
528+ func (service * OIDCService ) generateIDToken (client model.OIDCClientConfig , user UserinfoResponse , scope string , nonce string , authTime * int64 ) (string , error ) {
516529 createdAt := time .Now ().Unix ()
517530 expiresAt := time .Now ().Add (time .Duration (service .config .Auth .SessionExpiry ) * time .Second ).Unix ()
518531
@@ -557,6 +570,10 @@ func (service *OIDCService) generateIDToken(client model.OIDCClientConfig, user
557570 Nonce : nonce ,
558571 }
559572
573+ if authTime != nil {
574+ claims .AuthTime = * authTime
575+ }
576+
560577 payload , err := json .Marshal (claims )
561578
562579 if err != nil {
@@ -578,8 +595,8 @@ func (service *OIDCService) generateIDToken(client model.OIDCClientConfig, user
578595 return token , nil
579596}
580597
581- func (service * OIDCService ) GenerateAccessToken (ctx context.Context , client model.OIDCClientConfig , codeEntry AuthorizeCodeEntry ) (* TokenResponse , error ) {
582- idToken , err := service .generateIDToken (client , codeEntry .Userinfo , codeEntry .Scope , codeEntry .Nonce )
598+ func (service * OIDCService ) GenerateAccessToken (ctx context.Context , client model.OIDCClientConfig , codeEntry AuthorizeCodeEntry , authTime int64 ) (* TokenResponse , error ) {
599+ idToken , err := service .generateIDToken (client , codeEntry .Userinfo , codeEntry .Scope , codeEntry .Nonce , & authTime )
583600
584601 if err != nil {
585602 return nil , err
@@ -658,9 +675,10 @@ func (service *OIDCService) RefreshAccessToken(ctx context.Context, refreshToken
658675 return nil , err
659676 }
660677
678+ // TODO: store auth time in the database so we can include it in the new ID token, for now we omit it
661679 idToken , err := service .generateIDToken (model.OIDCClientConfig {
662680 ClientID : entry .ClientID ,
663- }, userInfo , entry .Scope , entry .Nonce )
681+ }, userInfo , entry .Scope , entry .Nonce , nil )
664682
665683 if err != nil {
666684 return nil , err
@@ -929,5 +947,24 @@ func (service *OIDCService) DecodeAuthorizeJWT(tokenString string) (*AuthorizeRe
929947 Nonce : get ("nonce" ),
930948 CodeChallenge : get ("code_challenge" ),
931949 CodeChallengeMethod : get ("code_challenge_method" ),
950+ Prompt : get ("prompt" ),
932951 }, nil
933952}
953+
954+ func (service * OIDCService ) GetPrompt (prompt string ) []OIDCPrompt {
955+ if prompt == "" {
956+ return []OIDCPrompt {}
957+ }
958+
959+ parsedPromps := make ([]OIDCPrompt , 0 )
960+ prompts := strings .SplitSeq (prompt , " " )
961+
962+ for p := range prompts {
963+ if ! slices .Contains (SupportedPrompts , p ) {
964+ continue
965+ }
966+ parsedPromps = append (parsedPromps , OIDCPrompt (p ))
967+ }
968+
969+ return parsedPromps
970+ }
0 commit comments