-
Notifications
You must be signed in to change notification settings - Fork 0
/
apis.go
97 lines (80 loc) · 2.87 KB
/
apis.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
// Package apis contains JWT claim values for Google Maps Platform APIs.
package apis
import (
"errors"
"strings"
)
const RoutesScope = "https://www.googleapis.com/auth/geo-platform.routes"
const RoutesAudience = "https://routes.googleapis.com/"
const AddressValidationScope = "https://www.googleapis.com/auth/maps-platform.addressvalidation"
const AddressValidationAudience = "https://addressvalidation.googleapis.com/"
const PlacesScope = "https://www.googleapis.com/auth/maps-platform.places"
const PlacesAudience = "https://places.googleapis.com/"
const TileScope = "https://www.googleapis.com/auth/maps-platform.tiles"
const TileAudience = "https://tile.googleapis.com/"
const GCPScope = "https://www.googleapis.com/auth/cloud-platform"
const AirQualityAudience = "https://airquality.googleapis.com/"
const SolarAudience = "https://solar.googleapis.com/"
// APITokenInfo represents the claims a JWT should include to authenticate.
type APITokenInfo struct {
Scope string
Audience string
}
// APIs maps shortnames of each API to information about their scope and audience.
var APIs = map[string]APITokenInfo{
"routes": {RoutesScope, RoutesAudience},
"addressvalidation": {AddressValidationScope, AddressValidationAudience},
"places": {PlacesScope, PlacesAudience},
"airquality": {GCPScope, AirQualityAudience},
"solar": {GCPScope, SolarAudience},
"tile": {TileScope, TileAudience},
}
var ErrIncompatibleAPIs = errors.New("request cannot include a multiple gcp-scoped apis or a mix of gcp-scoped and maps-scoped")
// Lookup returns scope and audience information suitable for the supplied APIs.
func Lookup(names []string) (*APITokenInfo, error) {
scopes := map[string]bool{}
audience := []string{}
token := APITokenInfo{}
if len(names) == 0 {
return &token, nil
}
if IsWildcard(names) {
for _, api := range APIs {
if api.Scope == GCPScope {
// Skip the GCPScope, it should be part of a wildcard.
continue
}
scopes[api.Scope] = true
audience = append(audience, api.Audience)
}
} else {
for _, name := range names {
if api, ok := APIs[name]; ok {
scopes[api.Scope] = true
audience = append(audience, api.Audience)
}
}
}
// An audience constraint can only be applied when the token has 1 audience.
if len(audience) == 1 {
token.Audience = audience[0]
}
// Never return a token that has the GCP scope and no audience.
// That token would grant too much access.
if token.Audience == "" {
if _, found := scopes[GCPScope]; found {
return nil, ErrIncompatibleAPIs
}
}
// Join together scopes with a space.
s := []string{}
for scope := range scopes {
s = append(s, scope)
}
token.Scope = strings.Join(s, " ")
return &token, nil
}
// IsWildcard identifies if list of API names actually means all APIs.
func IsWildcard(apis []string) bool {
return len(apis) >= 1 && apis[0] == "*"
}