2023-11-21 12:11:38 +00:00
|
|
|
package oidc
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"encoding/base64"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/zitadel/oidc/v3/pkg/oidc"
|
|
|
|
"golang.org/x/text/language"
|
|
|
|
|
|
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
|
|
"github.com/zitadel/zitadel/internal/query"
|
|
|
|
)
|
|
|
|
|
|
|
|
func Test_prepareRoles(t *testing.T) {
|
|
|
|
type args struct {
|
2024-04-09 13:15:35 +00:00
|
|
|
projectID string
|
|
|
|
scope []string
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
projectRoleAssertion bool
|
|
|
|
currentProjectOnly bool
|
2023-11-21 12:11:38 +00:00
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
args args
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
wantRoleAudience []string
|
2023-11-21 12:11:38 +00:00
|
|
|
wantRequestedRoles []string
|
|
|
|
}{
|
|
|
|
{
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
name: "empty scope",
|
2023-11-21 12:11:38 +00:00
|
|
|
args: args{
|
2024-04-09 13:15:35 +00:00
|
|
|
projectID: "projID",
|
|
|
|
scope: nil,
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
projectRoleAssertion: false,
|
|
|
|
currentProjectOnly: false,
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
wantRoleAudience: nil,
|
2023-11-21 12:11:38 +00:00
|
|
|
wantRequestedRoles: nil,
|
|
|
|
},
|
2024-04-09 13:15:35 +00:00
|
|
|
{
|
|
|
|
name: "project role assertion",
|
|
|
|
args: args{
|
|
|
|
projectID: "projID",
|
|
|
|
projectRoleAssertion: true,
|
|
|
|
scope: nil,
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
currentProjectOnly: false,
|
2024-04-09 13:15:35 +00:00
|
|
|
},
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
wantRoleAudience: []string{"projID"},
|
|
|
|
wantRequestedRoles: nil,
|
2024-04-09 13:15:35 +00:00
|
|
|
},
|
2023-11-21 12:11:38 +00:00
|
|
|
{
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
name: "some scope, current project only",
|
2023-11-21 12:11:38 +00:00
|
|
|
args: args{
|
2024-04-09 13:15:35 +00:00
|
|
|
projectID: "projID",
|
|
|
|
projectRoleAssertion: false,
|
|
|
|
scope: []string{"openid", "profile"},
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
currentProjectOnly: true,
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
wantRoleAudience: []string{"projID"},
|
|
|
|
wantRequestedRoles: nil,
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "scope projects roles",
|
|
|
|
args: args{
|
2024-04-09 13:15:35 +00:00
|
|
|
projectID: "projID",
|
|
|
|
projectRoleAssertion: false,
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
scope: []string{
|
|
|
|
"openid", "profile",
|
|
|
|
ScopeProjectsRoles,
|
|
|
|
domain.ProjectIDScope + "project2" + domain.AudSuffix,
|
|
|
|
},
|
|
|
|
currentProjectOnly: false,
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
wantRoleAudience: []string{"project2", "projID"},
|
|
|
|
wantRequestedRoles: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "scope projects roles ignored, current project only",
|
|
|
|
args: args{
|
|
|
|
projectID: "projID",
|
|
|
|
projectRoleAssertion: false,
|
|
|
|
scope: []string{
|
|
|
|
"openid", "profile",
|
|
|
|
ScopeProjectsRoles,
|
|
|
|
domain.ProjectIDScope + "project2" + domain.AudSuffix,
|
|
|
|
},
|
|
|
|
currentProjectOnly: true,
|
|
|
|
},
|
|
|
|
wantRoleAudience: []string{"projID"},
|
|
|
|
wantRequestedRoles: nil,
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "scope project role prefix",
|
|
|
|
args: args{
|
2024-04-09 13:15:35 +00:00
|
|
|
projectID: "projID",
|
|
|
|
projectRoleAssertion: false,
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
scope: []string{
|
|
|
|
"openid", "profile",
|
|
|
|
ScopeProjectRolePrefix + "foo",
|
|
|
|
ScopeProjectRolePrefix + "bar",
|
|
|
|
},
|
|
|
|
currentProjectOnly: false,
|
|
|
|
},
|
|
|
|
wantRoleAudience: []string{"projID"},
|
|
|
|
wantRequestedRoles: []string{"foo", "bar"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "scope project role prefix and audience",
|
|
|
|
args: args{
|
|
|
|
projectID: "projID",
|
|
|
|
projectRoleAssertion: false,
|
|
|
|
scope: []string{
|
|
|
|
"openid", "profile",
|
|
|
|
ScopeProjectRolePrefix + "foo",
|
|
|
|
ScopeProjectRolePrefix + "bar",
|
|
|
|
domain.ProjectIDScope + "project2" + domain.AudSuffix,
|
|
|
|
},
|
|
|
|
currentProjectOnly: false,
|
|
|
|
},
|
|
|
|
wantRoleAudience: []string{"projID", "project2"},
|
|
|
|
wantRequestedRoles: []string{"foo", "bar"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "scope project role prefix and audience ignored, current project only",
|
|
|
|
args: args{
|
|
|
|
projectID: "projID",
|
|
|
|
projectRoleAssertion: false,
|
|
|
|
scope: []string{
|
|
|
|
"openid", "profile",
|
|
|
|
ScopeProjectRolePrefix + "foo",
|
|
|
|
ScopeProjectRolePrefix + "bar",
|
|
|
|
domain.ProjectIDScope + "project2" + domain.AudSuffix,
|
|
|
|
},
|
|
|
|
currentProjectOnly: true,
|
|
|
|
},
|
|
|
|
wantRoleAudience: []string{"projID"},
|
|
|
|
wantRequestedRoles: []string{"foo", "bar"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no projectID, scope project role prefix and audience",
|
|
|
|
args: args{
|
|
|
|
projectID: "",
|
|
|
|
projectRoleAssertion: false,
|
|
|
|
scope: []string{
|
|
|
|
"openid", "profile",
|
|
|
|
ScopeProjectRolePrefix + "foo",
|
|
|
|
ScopeProjectRolePrefix + "bar",
|
|
|
|
domain.ProjectIDScope + "project2" + domain.AudSuffix,
|
|
|
|
},
|
|
|
|
currentProjectOnly: false,
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
wantRoleAudience: []string{"project2"},
|
2023-11-21 12:11:38 +00:00
|
|
|
wantRequestedRoles: []string{"foo", "bar"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
fix(oidc): roles in userinfo for client credentials token (#7763)
* fix(oidc): roles in userinfo for client credentials token
When tokens were obtained using the client credentials grant,
with audience and role scopes, userinfo would not return the role claims. This had multiple causes:
1. There is no auth request flow, so for legacy userinfo project data was never attached to the token
2. For optimized userinfo, there is no client ID that maps to an application. The client ID for client credentials is the machine user's name. There we can't obtain a project ID. When the project ID remained empty, we always ignored the roleAudience.
This PR fixes situation 2, by always taking the roleAudience into account, even when the projectID is empty. The code responsible for the bug is also refactored to be more readable and understandable, including additional godoc.
The fix only applies to the optimized userinfo code introduced in #7706 and released in v2.50 (currently in RC). Therefore it can't be back-ported to earlier versions.
Fixes #6662
* chore(deps): update all go deps (#7764)
This change updates all go modules, including oidc, a major version of go-jose and the go 1.22 release.
* Revert "chore(deps): update all go deps" (#7772)
Revert "chore(deps): update all go deps (#7764)"
This reverts commit 6893e7d060a953d595a18ff8daa979834c4324d5.
---------
Co-authored-by: Livio Spring <livio.a@gmail.com>
2024-04-16 13:02:38 +00:00
|
|
|
gotRoleAudience, gotRequestedRoles := prepareRoles(context.Background(), tt.args.scope, tt.args.projectID, tt.args.projectRoleAssertion, tt.args.currentProjectOnly)
|
|
|
|
assert.ElementsMatch(t, tt.wantRoleAudience, gotRoleAudience, "roleAudience")
|
|
|
|
assert.ElementsMatch(t, tt.wantRequestedRoles, gotRequestedRoles, "requestedRoles")
|
2023-11-21 12:11:38 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_userInfoToOIDC(t *testing.T) {
|
|
|
|
metadata := []query.UserMetadata{
|
|
|
|
{
|
|
|
|
Key: "key1",
|
|
|
|
Value: []byte{1, 2, 3},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: "key2",
|
|
|
|
Value: []byte{4, 5, 6},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
organization := &query.UserInfoOrg{
|
|
|
|
ID: "orgID",
|
|
|
|
Name: "orgName",
|
|
|
|
PrimaryDomain: "orgDomain",
|
|
|
|
}
|
|
|
|
humanUserInfo := &query.OIDCUserInfo{
|
|
|
|
User: &query.User{
|
|
|
|
ID: "human1",
|
|
|
|
CreationDate: time.Unix(123, 456),
|
|
|
|
ChangeDate: time.Unix(567, 890),
|
|
|
|
ResourceOwner: "orgID",
|
|
|
|
Sequence: 22,
|
|
|
|
State: domain.UserStateActive,
|
|
|
|
Type: domain.UserTypeHuman,
|
|
|
|
Username: "username",
|
|
|
|
LoginNames: []string{"foo", "bar"},
|
|
|
|
PreferredLoginName: "foo",
|
|
|
|
Human: &query.Human{
|
|
|
|
FirstName: "user",
|
|
|
|
LastName: "name",
|
|
|
|
NickName: "foobar",
|
|
|
|
DisplayName: "xxx",
|
|
|
|
AvatarKey: "picture.png",
|
|
|
|
PreferredLanguage: language.Dutch,
|
|
|
|
Gender: domain.GenderDiverse,
|
|
|
|
Email: "foo@bar.com",
|
|
|
|
IsEmailVerified: true,
|
|
|
|
Phone: "+31123456789",
|
|
|
|
IsPhoneVerified: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Metadata: metadata,
|
|
|
|
Org: organization,
|
|
|
|
UserGrants: []query.UserGrant{
|
|
|
|
{
|
|
|
|
ID: "ug1",
|
|
|
|
CreationDate: time.Unix(444, 444),
|
|
|
|
ChangeDate: time.Unix(555, 555),
|
|
|
|
Sequence: 55,
|
|
|
|
Roles: []string{"role1", "role2"},
|
|
|
|
GrantID: "grantID",
|
|
|
|
State: domain.UserGrantStateActive,
|
|
|
|
UserID: "human1",
|
|
|
|
Username: "username",
|
|
|
|
ResourceOwner: "orgID",
|
|
|
|
ProjectID: "project1",
|
|
|
|
OrgName: "orgName",
|
|
|
|
OrgPrimaryDomain: "orgDomain",
|
|
|
|
ProjectName: "projectName",
|
|
|
|
UserResourceOwner: "org1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
machineUserInfo := &query.OIDCUserInfo{
|
|
|
|
User: &query.User{
|
|
|
|
ID: "machine1",
|
|
|
|
CreationDate: time.Unix(123, 456),
|
|
|
|
ChangeDate: time.Unix(567, 890),
|
|
|
|
ResourceOwner: "orgID",
|
|
|
|
Sequence: 23,
|
|
|
|
State: domain.UserStateActive,
|
|
|
|
Type: domain.UserTypeMachine,
|
|
|
|
Username: "machine",
|
|
|
|
PreferredLoginName: "meanMachine",
|
|
|
|
Machine: &query.Machine{
|
|
|
|
Name: "machine",
|
|
|
|
Description: "I'm a robot",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Org: organization,
|
|
|
|
UserGrants: []query.UserGrant{
|
|
|
|
{
|
|
|
|
ID: "ug1",
|
|
|
|
CreationDate: time.Unix(444, 444),
|
|
|
|
ChangeDate: time.Unix(555, 555),
|
|
|
|
Sequence: 55,
|
|
|
|
Roles: []string{"role1", "role2"},
|
|
|
|
GrantID: "grantID",
|
|
|
|
State: domain.UserGrantStateActive,
|
|
|
|
UserID: "human1",
|
|
|
|
Username: "username",
|
|
|
|
ResourceOwner: "orgID",
|
|
|
|
ProjectID: "project1",
|
|
|
|
OrgName: "orgName",
|
|
|
|
OrgPrimaryDomain: "orgDomain",
|
|
|
|
ProjectName: "projectName",
|
|
|
|
UserResourceOwner: "org1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
type args struct {
|
2024-05-31 10:10:18 +00:00
|
|
|
user *query.OIDCUserInfo
|
|
|
|
userInfoAssertion bool
|
|
|
|
scope []string
|
2023-11-21 12:11:38 +00:00
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
args args
|
|
|
|
want *oidc.UserInfo
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "human, empty",
|
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: humanUserInfo,
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
2024-09-12 12:36:33 +00:00
|
|
|
want: &oidc.UserInfo{
|
|
|
|
Subject: "human1",
|
|
|
|
},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "machine, empty",
|
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: machineUserInfo,
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
2024-09-12 12:36:33 +00:00
|
|
|
want: &oidc.UserInfo{
|
|
|
|
Subject: "machine1",
|
|
|
|
},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "human, scope openid",
|
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: humanUserInfo,
|
|
|
|
scope: []string{oidc.ScopeOpenID},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
want: &oidc.UserInfo{
|
|
|
|
Subject: "human1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "machine, scope openid",
|
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: machineUserInfo,
|
|
|
|
scope: []string{oidc.ScopeOpenID},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
want: &oidc.UserInfo{
|
|
|
|
Subject: "machine1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-05-31 10:10:18 +00:00
|
|
|
name: "human, scope email, profileInfoAssertion",
|
2023-11-21 12:11:38 +00:00
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: humanUserInfo,
|
|
|
|
userInfoAssertion: true,
|
|
|
|
scope: []string{oidc.ScopeEmail},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
want: &oidc.UserInfo{
|
2024-09-12 12:36:33 +00:00
|
|
|
Subject: "human1",
|
2023-11-21 12:11:38 +00:00
|
|
|
UserInfoEmail: oidc.UserInfoEmail{
|
|
|
|
Email: "foo@bar.com",
|
|
|
|
EmailVerified: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-05-31 10:10:18 +00:00
|
|
|
name: "human, scope email",
|
2023-11-21 12:11:38 +00:00
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: humanUserInfo,
|
|
|
|
scope: []string{oidc.ScopeEmail},
|
|
|
|
},
|
2024-09-12 12:36:33 +00:00
|
|
|
want: &oidc.UserInfo{
|
|
|
|
Subject: "human1",
|
|
|
|
},
|
2024-05-31 10:10:18 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "machine, scope email, profileInfoAssertion",
|
|
|
|
args: args{
|
|
|
|
user: machineUserInfo,
|
|
|
|
scope: []string{oidc.ScopeEmail},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
want: &oidc.UserInfo{
|
2024-09-12 12:36:33 +00:00
|
|
|
Subject: "machine1",
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-05-31 10:10:18 +00:00
|
|
|
name: "human, scope profile, profileInfoAssertion",
|
2023-11-21 12:11:38 +00:00
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: humanUserInfo,
|
|
|
|
userInfoAssertion: true,
|
|
|
|
scope: []string{oidc.ScopeProfile},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
want: &oidc.UserInfo{
|
2024-09-12 12:36:33 +00:00
|
|
|
Subject: "human1",
|
2023-11-21 12:11:38 +00:00
|
|
|
UserInfoProfile: oidc.UserInfoProfile{
|
|
|
|
Name: "xxx",
|
|
|
|
GivenName: "user",
|
|
|
|
FamilyName: "name",
|
|
|
|
Nickname: "foobar",
|
|
|
|
Picture: "https://foo.com/assets/orgID/picture.png",
|
|
|
|
Gender: "diverse",
|
|
|
|
Locale: oidc.NewLocale(language.Dutch),
|
|
|
|
UpdatedAt: oidc.FromTime(time.Unix(567, 890)),
|
|
|
|
PreferredUsername: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-05-31 10:10:18 +00:00
|
|
|
name: "machine, scope profile, profileInfoAssertion",
|
2023-11-21 12:11:38 +00:00
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: machineUserInfo,
|
|
|
|
userInfoAssertion: true,
|
|
|
|
scope: []string{oidc.ScopeProfile},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
want: &oidc.UserInfo{
|
2024-09-12 12:36:33 +00:00
|
|
|
Subject: "machine1",
|
2023-11-21 12:11:38 +00:00
|
|
|
UserInfoProfile: oidc.UserInfoProfile{
|
|
|
|
Name: "machine",
|
|
|
|
UpdatedAt: oidc.FromTime(time.Unix(567, 890)),
|
|
|
|
PreferredUsername: "meanMachine",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
2024-05-31 10:10:18 +00:00
|
|
|
name: "machine, scope profile",
|
2023-11-21 12:11:38 +00:00
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: machineUserInfo,
|
|
|
|
scope: []string{oidc.ScopeProfile},
|
|
|
|
},
|
2024-09-12 12:36:33 +00:00
|
|
|
want: &oidc.UserInfo{
|
|
|
|
Subject: "machine1",
|
|
|
|
},
|
2024-05-31 10:10:18 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "human, scope phone, profileInfoAssertion",
|
|
|
|
args: args{
|
|
|
|
user: humanUserInfo,
|
|
|
|
userInfoAssertion: true,
|
|
|
|
scope: []string{oidc.ScopePhone},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
want: &oidc.UserInfo{
|
2024-09-12 12:36:33 +00:00
|
|
|
Subject: "human1",
|
2023-11-21 12:11:38 +00:00
|
|
|
UserInfoPhone: oidc.UserInfoPhone{
|
|
|
|
PhoneNumber: "+31123456789",
|
|
|
|
PhoneNumberVerified: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2024-05-31 10:10:18 +00:00
|
|
|
{
|
|
|
|
name: "human, scope phone",
|
|
|
|
args: args{
|
|
|
|
user: humanUserInfo,
|
|
|
|
scope: []string{oidc.ScopePhone},
|
|
|
|
},
|
2024-09-12 12:36:33 +00:00
|
|
|
want: &oidc.UserInfo{
|
|
|
|
Subject: "human1",
|
|
|
|
},
|
2024-05-31 10:10:18 +00:00
|
|
|
},
|
2023-11-21 12:11:38 +00:00
|
|
|
{
|
|
|
|
name: "machine, scope phone",
|
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: machineUserInfo,
|
|
|
|
scope: []string{oidc.ScopePhone},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
want: &oidc.UserInfo{
|
2024-09-12 12:36:33 +00:00
|
|
|
Subject: "machine1",
|
2023-11-21 12:11:38 +00:00
|
|
|
UserInfoPhone: oidc.UserInfoPhone{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "human, scope metadata",
|
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: humanUserInfo,
|
|
|
|
scope: []string{ScopeUserMetaData},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
want: &oidc.UserInfo{
|
2024-09-12 12:36:33 +00:00
|
|
|
Subject: "human1",
|
|
|
|
UserInfoEmail: oidc.UserInfoEmail{},
|
2023-11-21 12:11:38 +00:00
|
|
|
Claims: map[string]any{
|
|
|
|
ClaimUserMetaData: map[string]string{
|
|
|
|
"key1": base64.RawURLEncoding.EncodeToString([]byte{1, 2, 3}),
|
|
|
|
"key2": base64.RawURLEncoding.EncodeToString([]byte{4, 5, 6}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "machine, scope metadata, none found",
|
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: machineUserInfo,
|
|
|
|
scope: []string{ScopeUserMetaData},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
2024-09-12 12:36:33 +00:00
|
|
|
want: &oidc.UserInfo{
|
|
|
|
Subject: "machine1",
|
|
|
|
},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "machine, scope resource owner",
|
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: machineUserInfo,
|
|
|
|
scope: []string{ScopeResourceOwner},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
want: &oidc.UserInfo{
|
2024-09-12 12:36:33 +00:00
|
|
|
Subject: "machine1",
|
2023-11-21 12:11:38 +00:00
|
|
|
Claims: map[string]any{
|
2024-03-20 10:18:46 +00:00
|
|
|
ClaimResourceOwnerID: "orgID",
|
|
|
|
ClaimResourceOwnerName: "orgName",
|
|
|
|
ClaimResourceOwnerPrimaryDomain: "orgDomain",
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "human, scope org primary domain prefix",
|
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: humanUserInfo,
|
|
|
|
scope: []string{domain.OrgDomainPrimaryScope + "foo.com"},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
want: &oidc.UserInfo{
|
2024-09-12 12:36:33 +00:00
|
|
|
Subject: "human1",
|
2023-11-21 12:11:38 +00:00
|
|
|
Claims: map[string]any{
|
|
|
|
domain.OrgDomainPrimaryClaim: "foo.com",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "machine, scope org id",
|
|
|
|
args: args{
|
2024-05-31 10:10:18 +00:00
|
|
|
user: machineUserInfo,
|
|
|
|
scope: []string{domain.OrgIDScope + "orgID"},
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
want: &oidc.UserInfo{
|
2024-09-12 12:36:33 +00:00
|
|
|
Subject: "machine1",
|
2023-11-21 12:11:38 +00:00
|
|
|
Claims: map[string]any{
|
2024-03-20 10:18:46 +00:00
|
|
|
domain.OrgIDClaim: "orgID",
|
|
|
|
ClaimResourceOwnerID: "orgID",
|
|
|
|
ClaimResourceOwnerName: "orgName",
|
|
|
|
ClaimResourceOwnerPrimaryDomain: "orgDomain",
|
2023-11-21 12:11:38 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
assetPrefix := "https://foo.com/assets"
|
2024-05-31 10:10:18 +00:00
|
|
|
got := userInfoToOIDC(tt.args.user, tt.args.userInfoAssertion, tt.args.scope, assetPrefix)
|
2023-11-21 12:11:38 +00:00
|
|
|
assert.Equal(t, tt.want, got)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|