@@ -2,6 +2,8 @@ package providers
22
33import (
44 "context"
5+ "crypto/rand"
6+ "crypto/rsa"
57 "encoding/base64"
68 "net/http"
79 "net/http/httptest"
@@ -9,6 +11,7 @@ import (
911 "strings"
1012
1113 "github.com/coreos/go-oidc/v3/oidc"
14+ "github.com/dgrijalva/jwt-go"
1215 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
1316 . "github.com/onsi/ginkgo"
1417 . "github.com/onsi/ginkgo/extensions/table"
@@ -25,8 +28,18 @@ func (fakeADFSJwks) VerifySignature(_ context.Context, jwt string) (payload []by
2528 return decodeString, nil
2629}
2730
28−func testADFSProvider(hostname string) *ADFSProvider {
31+type adfsClaims struct {
32+ UPN string `json:"upn,omitempty"`
33+ idTokenClaims
34+}
35+
36+func newSignedTestADFSToken(tokenClaims adfsClaims) (string, error) {
37+ key, _ := rsa.GenerateKey(rand.Reader, 2048)
38+ standardClaims := jwt.NewWithClaims(jwt.SigningMethodRS256, tokenClaims)
39+ return standardClaims.SignedString(key)
40+}
2941
42+func testADFSProvider(hostname string) *ADFSProvider {
3043 o := oidc.NewVerifier(
3144 "https://issuer.example.com",
3245 fakeADFSJwks{},
@@ -41,6 +54,7 @@ func testADFSProvider(hostname string) *ADFSProvider {
4154 ValidateURL: &url.URL{},
4255 Scope: "",
4356 Verifier: o,
57+ EmailClaim: OIDCEmailClaim,
4458 })
4559
4660 if hostname != "" {
@@ -54,7 +68,6 @@ func testADFSProvider(hostname string) *ADFSProvider {
5468}
5569
5670func testADFSBackend() *httptest.Server {
57−
5871 authResponse := `
5972 {
6073 "access_token": "my_access_token",
@@ -129,7 +142,6 @@ var _ = Describe("ADFS Provider Tests", func() {
129142
130143 Context("with valid token", func() {
131144 It("should not throw an error", func() {
132− p.EmailClaim = "email"
133145 rawIDToken, _ := newSignedTestIDToken(defaultIDToken)
134146 idToken, err := p.Verifier.Verify(context.Background(), rawIDToken)
135147 Expect(err).To(BeNil())
@@ -202,4 +214,68 @@ var _ = Describe("ADFS Provider Tests", func() {
202214 }),
203215 )
204216 })
217+
218+ Context("UPN Fallback", func() {
219+ var idToken string
220+ var session *sessions.SessionState
221+
222+ BeforeEach(func() {
223+ var err error
224+ idToken, err = newSignedTestADFSToken(adfsClaims{
225+ UPN: "upn@company.com",
226+ idTokenClaims: minimalIDToken,
227+ })
228+ Expect(err).ToNot(HaveOccurred())
229+
230+ session = &sessions.SessionState{
231+ IDToken: idToken,
232+ }
233+ })
234+
235+ Describe("EnrichSession", func() {
236+ It("uses email claim if present", func() {
237+ p.oidcEnrichFunc = func(_ context.Context, s *sessions.SessionState) error {
238+ s.Email = "person@company.com"
239+ return nil
240+ }
241+
242+ err := p.EnrichSession(context.Background(), session)
243+ Expect(err).ToNot(HaveOccurred())
244+ Expect(session.Email).To(Equal("person@company.com"))
245+ })
246+
247+ It("falls back to UPN claim if Email is missing", func() {
248+ p.oidcEnrichFunc = func(_ context.Context, s *sessions.SessionState) error {
249+ return nil
250+ }
251+
252+ err := p.EnrichSession(context.Background(), session)
253+ Expect(err).ToNot(HaveOccurred())
254+ Expect(session.Email).To(Equal("upn@company.com"))
255+ })
256+ })
257+
258+ Describe("RefreshSession", func() {
259+ It("uses email claim if present", func() {
260+ p.oidcRefreshFunc = func(_ context.Context, s *sessions.SessionState) (bool, error) {
261+ s.Email = "person@company.com"
262+ return true, nil
263+ }
264+
265+ _, err := p.RefreshSession(context.Background(), session)
266+ Expect(err).ToNot(HaveOccurred())
267+ Expect(session.Email).To(Equal("person@company.com"))
268+ })
269+
270+ It("falls back to UPN claim if Email is missing", func() {
271+ p.oidcRefreshFunc = func(_ context.Context, s *sessions.SessionState) (bool, error) {
272+ return true, nil
273+ }
274+
275+ _, err := p.RefreshSession(context.Background(), session)
276+ Expect(err).ToNot(HaveOccurred())
277+ Expect(session.Email).To(Equal("upn@company.com"))
278+ })
279+ })
280+ })
205281})