17785: Adds test exposing a problem when trying to handle other users' tokens.
[arvados.git] / lib / controller / localdb / login_oidc.go
index 6ca53bf18475c955e0b6edaad8051963ef3e3740..6182469ac378d58b1e1f864bf4d98a6b48a022fb 100644 (file)
@@ -55,7 +55,8 @@ type oidcLoginController struct {
        EmailClaim             string            // OpenID claim to use as email address; typically "email"
        EmailVerifiedClaim     string            // If non-empty, ensure claim value is true before accepting EmailClaim; typically "email_verified"
        UsernameClaim          string            // If non-empty, use as preferred username
-       AcceptAccessTokenScope string            // If non-empty, accept any access token containing this scope as an API token
+       AcceptAccessToken      bool              // Accept access tokens as API tokens
+       AcceptAccessTokenScope string            // If non-empty, don't accept access tokens as API tokens unless they contain this scope
        AuthParams             map[string]string // Additional parameters to pass with authentication request
 
        // override Google People API base URL for testing purposes
@@ -176,12 +177,19 @@ func (ctrl *oidcLoginController) getAuthInfo(ctx context.Context, token *oauth2.
        } else if verified, _ := claims[ctrl.EmailVerifiedClaim].(bool); verified || ctrl.EmailVerifiedClaim == "" {
                // Fall back to this info if the People API call
                // (below) doesn't return a primary && verified email.
-               name, _ := claims["name"].(string)
-               if names := strings.Fields(strings.TrimSpace(name)); len(names) > 1 {
-                       ret.FirstName = strings.Join(names[0:len(names)-1], " ")
-                       ret.LastName = names[len(names)-1]
-               } else if len(names) > 0 {
-                       ret.FirstName = names[0]
+               givenName, _ := claims["given_name"].(string)
+               familyName, _ := claims["family_name"].(string)
+               if givenName != "" && familyName != "" {
+                       ret.FirstName = givenName
+                       ret.LastName = familyName
+               } else {
+                       name, _ := claims["name"].(string)
+                       if names := strings.Fields(strings.TrimSpace(name)); len(names) > 1 {
+                               ret.FirstName = strings.Join(names[0:len(names)-1], " ")
+                               ret.LastName = names[len(names)-1]
+                       } else if len(names) > 0 {
+                               ret.FirstName = names[0]
+                       }
                }
                ret.Email, _ = claims[ctrl.EmailClaim].(string)
        }
@@ -507,15 +515,16 @@ func (ta *oidcTokenAuthorizer) registerToken(ctx context.Context, tok string) er
 // return a 403 error, otherwise true (acceptable as an API token) or
 // false (pass through unmodified).
 //
+// Return false if configured not to accept access tokens at all.
+//
 // Note we don't check signature or expiry here. We are relying on the
 // caller to verify those separately (e.g., by calling the UserInfo
 // endpoint).
 func (ta *oidcTokenAuthorizer) checkAccessTokenScope(ctx context.Context, tok string) (bool, error) {
-       switch ta.ctrl.AcceptAccessTokenScope {
-       case "*":
-               return true, nil
-       case "":
+       if !ta.ctrl.AcceptAccessToken {
                return false, nil
+       } else if ta.ctrl.AcceptAccessTokenScope == "" {
+               return true, nil
        }
        var claims struct {
                Scope string `json:"scope"`