16669: Accept OIDC access token in federated requests.
[arvados.git] / lib / controller / federation.go
index ac239fb9b23f5c4c106034e2a910fb441b9c2218..419d8b01049b21d97ccebe6c5f9ec394208e1336 100644 (file)
@@ -152,7 +152,7 @@ type CurrentUser struct {
 // non-nil, true, nil -- if the token is valid
 func (h *Handler) validateAPItoken(req *http.Request, token string) (*CurrentUser, bool, error) {
        user := CurrentUser{Authorization: arvados.APIClientAuthorization{APIToken: token}}
-       db, err := h.db(req)
+       db, err := h.db(req.Context())
        if err != nil {
                ctxlog.FromContext(req.Context()).WithError(err).Debugf("validateAPItoken(%s): database error", token)
                return nil, false, err
@@ -189,7 +189,7 @@ func (h *Handler) validateAPItoken(req *http.Request, token string) (*CurrentUse
 }
 
 func (h *Handler) createAPItoken(req *http.Request, userUUID string, scopes []string) (*arvados.APIClientAuthorization, error) {
-       db, err := h.db(req)
+       db, err := h.db(req.Context())
        if err != nil {
                return nil, err
        }
@@ -263,17 +263,20 @@ func (h *Handler) saltAuthToken(req *http.Request, remote string) (updatedReq *h
                return updatedReq, nil
        }
 
+       ctxlog.FromContext(req.Context()).Debugf("saltAuthToken: cluster %s token %s remote %s", h.Cluster.ClusterID, creds.Tokens[0], remote)
        token, err := auth.SaltToken(creds.Tokens[0], remote)
 
-       if err == auth.ErrObsoleteToken {
-               // If the token exists in our own database, salt it
-               // for the remote. Otherwise, assume it was issued by
-               // the remote, and pass it through unmodified.
+       if err == auth.ErrObsoleteToken || err == auth.ErrTokenFormat {
+               // If the token exists in our own database for our own
+               // user, salt it for the remote. Otherwise, assume it
+               // was issued by the remote, and pass it through
+               // unmodified.
                currentUser, ok, err := h.validateAPItoken(req, creds.Tokens[0])
                if err != nil {
                        return nil, err
-               } else if !ok {
-                       // Not ours; pass through unmodified.
+               } else if !ok || strings.HasPrefix(currentUser.UUID, remote) {
+                       // Unknown, or cached + belongs to remote;
+                       // pass through unmodified.
                        token = creds.Tokens[0]
                } else {
                        // Found; make V2 version and salt it.