git.iko.soy/typeable/oauth2-proxy
on master help sign in
144 lines 3.9 kB history raw
1package providers
3import (
4 "context"
5 "encoding/json"
6 "errors"
7 "fmt"
9 "github.com/bitly/go-simplejson"
10 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
11 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
12 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
13 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/requests"
16type GroupsClaimList []GroupClaimEntry
18type GroupClaimEntry struct {
19 GroupID string `json:"groupId"`
20 Roles []string `json:"roles"`
23// CIDAASProvider represents an CIDAAS based Identity Provider
24type CIDAASProvider struct {
25 *OIDCProvider
28var _ Provider = (*CIDAASProvider)(nil)
30const (
31 CidaasProviderName = "CIDAAS"
32 CidaasGroupName = "cidaas"
33 CidaasDefaultScope = "openid email profile roles groups"
36// NewCIDAASProvider initiates a new CIDAASProvider
37func NewCIDAASProvider(p *ProviderData, opts options.Provider) *CIDAASProvider {
38 p.setProviderDefaults(providerDefaults{
39 name: CidaasProviderName,
40 scope: CidaasDefaultScope,
41 })
43 return &CIDAASProvider{
44 OIDCProvider: NewOIDCProvider(p, opts.OIDCConfig),
45 }
48// RefreshSession uses the RefreshToken to fetch new Access and ID Tokens
49func (p *CIDAASProvider) RefreshSession(ctx context.Context, s *sessions.SessionState) (bool, error) {
50 if s == nil || s.RefreshToken == "" {
51 return false, nil
52 }
54 if err := p.redeemRefreshToken(ctx, s); err != nil {
55 return false, fmt.Errorf("unable to redeem refresh token: %w", err)
56 }
58 if err := p.EnrichSession(ctx, s); err != nil {
59 return false, fmt.Errorf("unable to enrich session data after refresh: %w %v", err, s)
60 }
62 return true, nil
65// EnrichSession data to add email an groups
66func (p *CIDAASProvider) EnrichSession(ctx context.Context, s *sessions.SessionState) error {
67 if p.ProfileURL.String() == "" && s.Email == "" {
68 return errors.New("id_token did not contain an email and profileURL is not defined")
69 } else if p.ProfileURL.String() == "" {
70 return nil
71 }
73 // Try to get missing emails or groups from a profileURL
74 if err := p.enrichFromUserinfoEndpoint(ctx, s); err != nil {
75 logger.Errorf("Warning: Profile URL request failed: %s", err)
76 }
78 // If a mandatory email wasn't set, error at this point.
79 if s.Email == "" {
80 return errors.New("neither the id_token nor the profileURL set an email")
81 }
82 return nil
85// enrichFromUserinfoEndpoint enriches a session's Email & Groups via the JSON response of
86// an OIDC profile URL
87func (p *CIDAASProvider) enrichFromUserinfoEndpoint(ctx context.Context, s *sessions.SessionState) error {
88 // profile url is userinfo url in case of Cidaas
89 respJSON, err := requests.New(p.ProfileURL.String()).
90 WithContext(ctx).
91 WithHeaders(makeOIDCHeader(s.AccessToken)).
92 Do().
93 UnmarshalSimpleJSON()
94 if err != nil {
95 return err
96 }
98 email, err := respJSON.Get(p.EmailClaim).String()
99 if err == nil && s.Email == "" {
100 s.Email = email
101 }
103 groups, err := p.extractGroups(respJSON)
104 if err != nil {
105 return fmt.Errorf("extracting groups failed: %w", err)
106 }
108 s.Groups = groups
109 return nil
112func (p *CIDAASProvider) extractGroups(respJSON *simplejson.Json) ([]string, error) {
113 rawGroupsClaim, err := respJSON.Get(p.GroupsClaim).MarshalJSON()
114 if err != nil {
115 return nil, err
116 }
118 var groupsClaimList GroupsClaimList
119 err = json.Unmarshal(rawGroupsClaim, &groupsClaimList)
120 if err != nil {
121 return nil, err
122 }
124 var groups []string
125 for _, group := range groupsClaimList {
126 for _, role := range group.Roles {
127 groups = append(groups, fmt.Sprintf("%s:%s", group.GroupID, role))
128 }
129 }
131 // Cidaas specific roles
132 if rolesVal, rolesClaimExists := respJSON.CheckGet("roles"); rolesClaimExists {
133 cidaasRoles, err := rolesVal.StringArray()
134 if err != nil {
135 return nil, fmt.Errorf("unmarshal roles failed: %w", err)
136 }
138 for _, role := range cidaasRoles {
139 groups = append(groups, fmt.Sprintf("%s:%s", CidaasGroupName, role))
140 }
141 }
143 return groups, nil