This is an automated email from the ASF dual-hosted git repository.

rshah pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new fbd097b12a Use ID token for OAuth authentication, not Access Token 
(#7621)
fbd097b12a is described below

commit fbd097b12ae7a36a91ecb357009647fb74d5cb51
Author: Zach Hoffman <[email protected]>
AuthorDate: Mon Jul 10 10:57:34 2023 -0600

    Use ID token for OAuth authentication, not Access Token (#7621)
    
    * Use ID token for OAuth authentication, not Access Token
    
    * Do not panic on non-existent attribute
    
    * Add oauth_user_attribute to cdn.conf too
---
 CHANGELOG.md                                  |  1 +
 lib/go-rfc/jwt.go                             | 28 +++++++++++++++++++++++++++
 traffic_ops/app/conf/cdn.conf                 |  1 +
 traffic_ops/traffic_ops_golang/api/api.go     |  9 +++------
 traffic_ops/traffic_ops_golang/cdni/shared.go |  2 +-
 traffic_ops/traffic_ops_golang/login/login.go | 25 ++++++++++++++----------
 6 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 01b48f0492..819a5a8523 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -62,6 +62,7 @@ The format is based on [Keep a 
Changelog](http://keepachangelog.com/en/1.0.0/).
 - [#7469](https://github.com/apache/trafficcontrol/pull/7469) *Traffic Ops* 
Changed logic to not report empty or missing cookies into TO error.log.
 - [#7586](https://github.com/apache/trafficcontrol/pull/7586) *Traffic Ops* 
Add permission to Operations Role to read from dnsseckeys endpoint.
 - [#7600](https://github.com/apache/trafficcontrol/pull/7600) *t3c* changed 
default go-direct command line arg to be old to avoid unexpected config changes 
upon upgrade.
+- [#7621](https://github.com/apache/trafficcontrol/pull/7621) *Traffic Ops* 
Use ID token for OAuth authentication, not Access Token
 
 ### Fixed
 - [#7623] (https://github.com/apache/trafficcontrol/pull/7623) *Traffic Ops* 
Removed TryIfModifiedSinceQuery from servicecategories.go and reused from ims.go
diff --git a/lib/go-rfc/jwt.go b/lib/go-rfc/jwt.go
new file mode 100644
index 0000000000..cfc39da28b
--- /dev/null
+++ b/lib/go-rfc/jwt.go
@@ -0,0 +1,28 @@
+package rfc
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+const (
+       // AccessToken is the access_token parameter name described in RFC 6749 
<https://datatracker.ietf.org/doc/html/rfc6749#section-1.4>.
+       AccessToken = "access_token"
+
+       // IDToken is the id_token parameter name described in OpenID Connect 
Core <https://openid.net/specs/openid-connect-core-1_0.html#IDToken>.
+       IDToken = "id_token"
+)
diff --git a/traffic_ops/app/conf/cdn.conf b/traffic_ops/app/conf/cdn.conf
index c4b6a8831b..f2fee94173 100644
--- a/traffic_ops/app/conf/cdn.conf
+++ b/traffic_ops/app/conf/cdn.conf
@@ -23,6 +23,7 @@
         "db_query_timeout_seconds": 20,
         "whitelisted_oauth_urls": [],
         "oauth_client_secret": "",
+        "oauth_user_attribute": "changeme",
         "traffic_vault_backend": "",
         "traffic_vault_config": {},
         "routing_blacklist": {
diff --git a/traffic_ops/traffic_ops_golang/api/api.go 
b/traffic_ops/traffic_ops_golang/api/api.go
index f8b95f5e65..119377404c 100644
--- a/traffic_ops/traffic_ops_golang/api/api.go
+++ b/traffic_ops/traffic_ops_golang/api/api.go
@@ -83,10 +83,7 @@ const (
        TrafficVaultContextKey = "tv"
 )
 
-const (
-       MojoCookie  = "mojoCookie"
-       AccessToken = "access_token"
-)
+const MojoCookie = "mojoCookie"
 
 const influxServersQuery = `
 SELECT (host_name||'.'||domain_name) as fqdn,
@@ -1091,7 +1088,7 @@ func GetUserFromReq(w http.ResponseWriter, r 
*http.Request, secret string) (auth
                                continue
                        }
                        switch givenCookie.Name {
-                       case AccessToken:
+                       case rfc.AccessToken:
                                bearerCookie, readToken, err := 
getCookieFromAccessToken(givenCookie.Value, secret)
                                if err != nil {
                                        return auth.CurrentUser{}, 
errors.New("unauthorized, please log in."), err, http.StatusUnauthorized
@@ -1155,7 +1152,7 @@ func GetUserFromReq(w http.ResponseWriter, r 
*http.Request, secret string) (auth
                }
 
                http.SetCookie(w, &http.Cookie{
-                       Name:     AccessToken,
+                       Name:     rfc.AccessToken,
                        Value:    string(jwtSigned),
                        Path:     "/",
                        MaxAge:   newCookie.MaxAge,
diff --git a/traffic_ops/traffic_ops_golang/cdni/shared.go 
b/traffic_ops/traffic_ops_golang/cdni/shared.go
index 22dbe883b6..117d624c40 100644
--- a/traffic_ops/traffic_ops_golang/cdni/shared.go
+++ b/traffic_ops/traffic_ops_golang/cdni/shared.go
@@ -115,7 +115,7 @@ func getBearerToken(r *http.Request) string {
        }
        for _, cookie := range r.Cookies() {
                switch cookie.Name {
-               case api.AccessToken:
+               case rfc.AccessToken:
                        return cookie.Value
                }
        }
diff --git a/traffic_ops/traffic_ops_golang/login/login.go 
b/traffic_ops/traffic_ops_golang/login/login.go
index 95a2959c46..e21b5cc5e9 100644
--- a/traffic_ops/traffic_ops_golang/login/login.go
+++ b/traffic_ops/traffic_ops_golang/login/login.go
@@ -263,7 +263,7 @@ func LoginHandler(db *sqlx.DB, cfg config.Config) 
http.HandlerFunc {
                }
 
                http.SetCookie(w, &http.Cookie{
-                       Name:     api.AccessToken,
+                       Name:     rfc.AccessToken,
                        Value:    string(jwtSigned),
                        Path:     "/",
                        MaxAge:   httpCookie.MaxAge,
@@ -459,17 +459,17 @@ func OauthLoginHandler(db *sqlx.DB, cfg config.Config) 
http.HandlerFunc {
 
                var result map[string]interface{}
                if err := json.Unmarshal(buf.Bytes(), &result); err != nil {
-                       log.Warnf("Error parsing JSON response from oAuth: %s", 
err)
+                       log.Warnf("Error parsing JSON response from OAuth: %s", 
err)
                        encodedToken = buf.String()
-               } else if _, ok := result[api.AccessToken]; !ok {
+               } else if _, ok := result[rfc.IDToken]; !ok {
                        sysErr := fmt.Errorf("Missing access token in response: 
%s\n", buf.String())
                        usrErr := errors.New("Bad response from OAuth2.0 
provider")
                        api.HandleErr(w, r, nil, http.StatusBadGateway, usrErr, 
sysErr)
                        return
                } else {
-                       switch t := result[api.AccessToken].(type) {
+                       switch t := result[rfc.IDToken].(type) {
                        case string:
-                               encodedToken = result[api.AccessToken].(string)
+                               encodedToken = result[rfc.IDToken].(string)
                        default:
                                sysErr := fmt.Errorf("Incorrect type of 
access_token! Expected 'string', got '%v'\n", t)
                                usrErr := errors.New("Bad response from 
OAuth2.0 provider")
@@ -499,14 +499,19 @@ func OauthLoginHandler(db *sqlx.DB, cfg config.Config) 
http.HandlerFunc {
                        }
                }
 
-               var userId string
+               var userIDInterface interface{}
+               var userID string
+               var ok bool
                if cfg.OAuthUserAttribute != "" {
                        attributes := decodedToken.PrivateClaims()
-                       userId = attributes[cfg.OAuthUserAttribute].(string)
+                       if userIDInterface, ok = 
attributes[cfg.OAuthUserAttribute]; !ok {
+                               api.HandleErr(w, r, nil, 
http.StatusInternalServerError, nil, fmt.Errorf("Non-existent OAuth attribute : 
%s", cfg.OAuthUserAttribute))
+                       }
+                       userID = userIDInterface.(string)
                } else {
-                       userId = decodedToken.Subject()
+                       userID = decodedToken.Subject()
                }
-               form.Username = userId
+               form.Username = userID
 
                dbCtx, cancelTx := context.WithTimeout(r.Context(), 
time.Duration(cfg.DBQueryTimeoutSeconds)*time.Second)
                defer cancelTx()
@@ -526,7 +531,7 @@ func OauthLoginHandler(db *sqlx.DB, cfg config.Config) 
http.HandlerFunc {
                                api.HandleErr(w, r, nil, 
http.StatusInternalServerError, nil, dbErr)
                                return
                        }
-                       httpCookie := tocookie.GetCookie(userId, 
defaultCookieDuration, cfg.Secrets[0])
+                       httpCookie := tocookie.GetCookie(userID, 
defaultCookieDuration, cfg.Secrets[0])
                        http.SetCookie(w, httpCookie)
                        resp = struct {
                                tc.Alerts

Reply via email to