1
1
package gitlab
2
2
3
3
import (
4
- "errors "
4
+ "fmt "
5
5
"net/http"
6
6
"net/url"
7
7
"path"
8
+ "strconv"
8
9
9
10
"github.com/openshift/origin/pkg/oauthserver/oauth/external"
10
11
"github.com/openshift/origin/pkg/oauthserver/oauth/external/openid"
@@ -23,7 +24,8 @@ const (
23
24
// The ability to authenticate using GitLab, and read-only access to the user's profile information and group memberships
24
25
gitlabOIDCScope = "openid"
25
26
26
- // An opaque token that uniquely identifies the user
27
+ // The ID of the user
28
+ // See above comment about GitLab 11.1.0 and the custom IDTokenValidator below
27
29
// Along with providerName, builds the identity object's Name field (see Identity.ProviderUserName)
28
30
gitlabIDClaim = "sub"
29
31
// The user's GitLab username
@@ -41,7 +43,7 @@ func NewProvider(providerName, URL, clientID, clientSecret string, transport htt
41
43
// Create service URLs
42
44
u , err := url .Parse (URL )
43
45
if err != nil {
44
- return nil , errors . New ("gitlab host URL is invalid" )
46
+ return nil , fmt . Errorf ("gitlab host URL %q is invalid" , URL )
45
47
}
46
48
47
49
config := openid.Config {
@@ -58,6 +60,22 @@ func NewProvider(providerName, URL, clientID, clientSecret string, transport htt
58
60
PreferredUsernameClaims : []string {gitlabPreferredUsernameClaim },
59
61
EmailClaims : []string {gitlabEmailClaim },
60
62
NameClaims : []string {gitlabDisplayNameClaim },
63
+
64
+ // make sure that gitlabIDClaim is a valid uint64, see above comment about GitLab 11.1.0
65
+ IDTokenValidator : func (idTokenClaims map [string ]interface {}) error {
66
+ gitlabID , ok := idTokenClaims [gitlabIDClaim ].(string )
67
+ if ! ok {
68
+ return nil // this is an OIDC spec violation which is handled by the default code path
69
+ }
70
+ if isPossibleSHA256HexDigest (gitlabID ) {
71
+ return fmt .Errorf ("incompatible gitlab IDP, ID claim %s=%s is SHA256 hex digest instead of digit" ,
72
+ gitlabIDClaim , gitlabID )
73
+ }
74
+ if ! isValidUint64 (gitlabID , 10 ) {
75
+ return fmt .Errorf ("invalid gitlab IDP, ID claim %s=%s is not a digit" , gitlabIDClaim , gitlabID )
76
+ }
77
+ return nil
78
+ },
61
79
}
62
80
63
81
return openid .NewProvider (providerName , transport , config )
@@ -67,3 +85,19 @@ func appendPath(u url.URL, subpath string) string {
67
85
u .Path = path .Join (u .Path , subpath )
68
86
return u .String ()
69
87
}
88
+
89
+ func isPossibleSHA256HexDigest (s string ) bool {
90
+ const (
91
+ // Have 256 bits from hex digest
92
+ // In hexadecimal each digit encodes 4 bits
93
+ // Thus we need 64 digits to represent 256 bits
94
+ sha256Len = 256 / 4
95
+ hexBase = 16
96
+ )
97
+ return len (s ) == sha256Len && isValidUint64 (s , hexBase )
98
+ }
99
+
100
+ func isValidUint64 (s string , base int ) bool {
101
+ _ , err := strconv .ParseUint (s , base , 64 )
102
+ return err == nil
103
+ }
0 commit comments