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