feat(op): allow scope without openid

This changes removes the requirement of the openid scope to be set for all token requests.
As this library also support OAuth2-only authentication mechanisms we still want to sanitize requested scopes, but not enforce the openid scope.

Related to https://github.com/zitadel/zitadel/discussions/8068
This commit is contained in:
Tim Möhlmann 2024-06-12 11:06:52 +02:00
parent 9ecdd0cf9a
commit 0c1430724f
2 changed files with 8 additions and 36 deletions

View file

@ -11,6 +11,7 @@ import (
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
"slices"
"strings" "strings"
"time" "time"
@ -250,37 +251,23 @@ func ValidateAuthReqPrompt(prompts []string, maxAge *uint) (_ *uint, err error)
return maxAge, nil return maxAge, nil
} }
// ValidateAuthReqScopes validates the passed scopes // ValidateAuthReqScopes validates the passed scopes and deletes any unsupported scopes.
// An error is returned if scopes is empty.
func ValidateAuthReqScopes(client Client, scopes []string) ([]string, error) { func ValidateAuthReqScopes(client Client, scopes []string) ([]string, error) {
if len(scopes) == 0 { if len(scopes) == 0 {
return nil, oidc.ErrInvalidRequest(). return nil, oidc.ErrInvalidRequest().
WithDescription("The scope of your request is missing. Please ensure some scopes are requested. " + WithDescription("The scope of your request is missing. Please ensure some scopes are requested. " +
"If you have any questions, you may contact the administrator of the application.") "If you have any questions, you may contact the administrator of the application.")
} }
openID := false scopes = slices.DeleteFunc(scopes, func(scope string) bool {
for i := len(scopes) - 1; i >= 0; i-- { return !(scope == oidc.ScopeOpenID ||
scope := scopes[i] scope == oidc.ScopeProfile ||
if scope == oidc.ScopeOpenID {
openID = true
continue
}
if !(scope == oidc.ScopeProfile ||
scope == oidc.ScopeEmail || scope == oidc.ScopeEmail ||
scope == oidc.ScopePhone || scope == oidc.ScopePhone ||
scope == oidc.ScopeAddress || scope == oidc.ScopeAddress ||
scope == oidc.ScopeOfflineAccess) && scope == oidc.ScopeOfflineAccess) &&
!client.IsScopeAllowed(scope) { !client.IsScopeAllowed(scope)
scopes[i] = scopes[len(scopes)-1] })
scopes[len(scopes)-1] = ""
scopes = scopes[:len(scopes)-1]
}
}
if !openID {
return nil, oidc.ErrInvalidScope().WithDescription("The scope openid is missing in your request. " +
"Please ensure the scope openid is added to the request. " +
"If you have any questions, you may contact the administrator of the application.")
}
return scopes, nil return scopes, nil
} }

View file

@ -137,11 +137,6 @@ func TestValidateAuthRequest(t *testing.T) {
args{&oidc.AuthRequest{}, mock.NewMockStorageExpectValidClientID(t), nil}, args{&oidc.AuthRequest{}, mock.NewMockStorageExpectValidClientID(t), nil},
oidc.ErrInvalidRequest(), oidc.ErrInvalidRequest(),
}, },
{
"scope openid missing fails",
args{&oidc.AuthRequest{Scopes: []string{"profile"}}, mock.NewMockStorageExpectValidClientID(t), nil},
oidc.ErrInvalidScope(),
},
{ {
"response_type missing fails", "response_type missing fails",
args{&oidc.AuthRequest{Scopes: []string{"openid"}}, mock.NewMockStorageExpectValidClientID(t), nil}, args{&oidc.AuthRequest{Scopes: []string{"openid"}}, mock.NewMockStorageExpectValidClientID(t), nil},
@ -287,16 +282,6 @@ func TestValidateAuthReqScopes(t *testing.T) {
err: true, err: true,
}, },
}, },
{
"scope openid missing fails",
args{
mock.NewClientExpectAny(t, op.ApplicationTypeWeb),
[]string{"email"},
},
res{
err: true,
},
},
{ {
"scope ok", "scope ok",
args{ args{