-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathclaims.go
133 lines (109 loc) · 3.95 KB
/
claims.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
* SPDX-License-Identifier: AGPL-3.0-or-later
* Copyright 2018 Kopano and its licensors
*/
package kcoidc
import (
"github.com/dgrijalva/jwt-go"
)
// Token claims used by Kopano Konnect.
const (
IsAccessTokenClaim = "kc.isAccessToken"
IsRefreshTokenClaim = "kc.isRefreshToken"
IdentityClaim = "kc.identity"
IdentifiedUserIDClaim = "kc.i.id"
IdentifiedUserIsGuest = "kc.i.guest"
AuthorizedScopesClaim = "kc.authorizedScopes"
AuthorizedClaimsClaim = "kc.authorizedClaims"
)
// Token types as int.
const (
TokenTypeStandard int = 0
TokenTypeKCAccess int = 1
TokenTypeKCRefresh int = 2
)
// ExtraClaimsWithType is a MapClaims with a specific type.
type ExtraClaimsWithType jwt.MapClaims
// Valid satisfies the jwt.Claims interface.
func (claims *ExtraClaimsWithType) Valid() error {
return nil
}
// KCTokenType returns the numeric type of the accociated claims.
func (claims *ExtraClaimsWithType) KCTokenType() int {
if v, _ := (*claims)[IsAccessTokenClaim].(bool); v {
return TokenTypeKCAccess
}
if v, _ := (*claims)[IsRefreshTokenClaim].(bool); v {
return TokenTypeKCRefresh
}
return TokenTypeStandard
}
// SplitStandardClaimsFromMapClaims removes all JWT standard claims from the
// provided map claims and returns them.
func SplitStandardClaimsFromMapClaims(claims *ExtraClaimsWithType) (*jwt.StandardClaims, error) {
std := &jwt.StandardClaims{
Audience: popStringFromMap(*claims, "aud"),
ExpiresAt: popInt64FromMap(*claims, "exp"),
Id: popStringFromMap(*claims, "jti"),
IssuedAt: popInt64FromMap(*claims, "iat"),
Issuer: popStringFromMap(*claims, "iss"),
NotBefore: popInt64FromMap(*claims, "nbf"),
Subject: popStringFromMap(*claims, "sub"),
}
return std, nil
}
// AuthenticatedUserIDFromClaims extracts extra Kopano Connect identified claims
// from the provided extra claims, returning the authenticated user id.
func AuthenticatedUserIDFromClaims(claims *ExtraClaimsWithType) (string, bool) {
if identityClaims, _ := (*claims)[IdentityClaim].(map[string]interface{}); identityClaims != nil {
if authenticatedUserID, _ := identityClaims[IdentifiedUserIDClaim].(string); authenticatedUserID != "" {
return authenticatedUserID, true
}
}
return "", false
}
// AuthenticatedUserIsGuest extract extra Kopano Connect identified claims from
// the provided extra claims, returning if the claims are for a guest or not.
func AuthenticatedUserIsGuest(claims *ExtraClaimsWithType) bool {
if identityClaims, _ := (*claims)[IdentityClaim].(map[string]interface{}); identityClaims != nil {
isGuest, _ := identityClaims[IdentifiedUserIsGuest].(bool)
return isGuest
}
return false
}
// AuthorizedScopesFromClaims returns the authorized scopes as bool map from
// the provided extra claims.
func AuthorizedScopesFromClaims(claims *ExtraClaimsWithType) map[string]bool {
if authorizedScopes, _ := (*claims)[AuthorizedScopesClaim].([]interface{}); authorizedScopes != nil {
authorizedScopesMap := make(map[string]bool)
for _, scope := range authorizedScopes {
authorizedScopesMap[scope.(string)] = true
}
return authorizedScopesMap
}
return nil
}
// AuthorizedClaimsFromClaims returns the authorized claims as map from the
// provided extra claims.
func AuthorizedClaimsFromClaims(claims *ExtraClaimsWithType) map[string]interface{} {
authorizedClaims, _ := (*claims)[AuthorizedClaimsClaim].(map[string]interface{})
return authorizedClaims
}
// RequireScopesInClaims returns nil if all the provided scopes are found in
// the provided claims. Otherwise an error is returned.
func RequireScopesInClaims(claims *ExtraClaimsWithType, requiredScopes []string) error {
if len(requiredScopes) == 0 {
return nil
}
authorizedScopes := AuthorizedScopesFromClaims(claims)
missingScopes := make([]string, 0)
for _, scope := range requiredScopes {
if ok, _ := authorizedScopes[scope]; !ok {
missingScopes = append(missingScopes, scope)
}
}
if len(missingScopes) == 0 {
return nil
}
return ErrStatusMissingRequiredScope
}