-
Notifications
You must be signed in to change notification settings - Fork 117
/
oidcprovider.go
116 lines (98 loc) · 4.8 KB
/
oidcprovider.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
package authnmock
import (
"context"
"crypto/rand"
"crypto/rsa"
"encoding/json"
"fmt"
"math"
"net"
"net/http"
"net/http/httptest"
"github.com/dgrijalva/jwt-go"
"gopkg.in/square/go-jose.v2"
)
const openIDConfiguration = `{"issuer":"http://foo.example.com","authorization_endpoint":"http://foo.example.com/oauth2/v1/authorize","token_endpoint":"http://foo.example.com/oauth2/v1/token","userinfo_endpoint":"http://foo.example.com/oauth2/v1/userinfo","registration_endpoint":"http://foo.example.com/oauth2/v1/clients","jwks_uri":"http://foo.example.com/oauth2/v1/keys","response_types_supported":["code","id_token","code id_token","code token","id_token token","code id_token token"],"response_modes_supported":["query","fragment","form_post","okta_post_message"],"grant_types_supported":["authorization_code","implicit","refresh_token","password"],"subject_types_supported":["public"],"id_token_signing_alg_values_supported":["RS256"],"scopes_supported":["openid","email","profile","address","phone","offline_access","groups"],"token_endpoint_auth_methods_supported":["client_secret_basic","client_secret_post","client_secret_jwt","private_key_jwt","none"],"claims_supported":["iss","ver","sub","aud","iat","exp","jti","auth_time","amr","idp","nonce","name","nickname","preferred_username","given_name","middle_name","family_name","email","email_verified","profile","zoneinfo","locale","address","phone_number","picture","website","gender","birthdate","updated_at","at_hash","c_hash"],"code_challenge_methods_supported":["S256"],"introspection_endpoint":"http://foo.example.com/oauth2/v1/introspect","introspection_endpoint_auth_methods_supported":["client_secret_basic","client_secret_post","client_secret_jwt","private_key_jwt","none"],"revocation_endpoint":"http://foo.example.com/oauth2/v1/revoke","revocation_endpoint_auth_methods_supported":["client_secret_basic","client_secret_post","client_secret_jwt","private_key_jwt","none"],"end_session_endpoint":"http://foo.example.com/oauth2/v1/logout","request_parameter_supported":true,"request_object_signing_alg_values_supported":["HS256","HS384","HS512","RS256","RS384","RS512","ES256","ES384","ES512"]}`
func NewMockOIDCProviderServer(email string, groups []string, customGroups []string) *MockOIDCProviderServer {
key, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
panic(err)
}
m := &MockOIDCProviderServer{
Key: key,
email: email,
groups: groups,
customGroupsClaim: customGroups,
}
m.srv = httptest.NewServer(http.HandlerFunc(m.handle))
m.client = m.srv.Client()
m.client.Transport = &http.Transport{DialContext: func(_ context.Context, network, _ string) (net.Conn, error) {
// Redirect all requests to the httptest server regardless of host.
return net.Dial(network, m.srv.Listener.Addr().String())
}}
return m
}
type MockOIDCProviderServer struct {
Key *rsa.PrivateKey
srv *httptest.Server
client *http.Client
email string
groups []string
customClaim string
customGroupsClaim []string
TokenCount int
}
type testIdTokenClaims struct {
*jwt.StandardClaims
Email string `json:"email"`
Groups []string `json:"groups"`
CustomClaim string `json:"custom_claim"`
CustomGroupsClaim []string `json:"custom_groups_claim"`
}
func (m *MockOIDCProviderServer) SetGroupClaim(groups []string) {
m.groups = groups
}
func (m *MockOIDCProviderServer) SetCustomClaim(customClaim string) {
m.customClaim = customClaim
}
func (m *MockOIDCProviderServer) SetCustomGroupClaim(customGroups []string) {
m.customGroupsClaim = customGroups
}
func (m *MockOIDCProviderServer) Close() {
m.srv.Close()
}
func (m *MockOIDCProviderServer) Client() *http.Client {
return m.client
}
func (m *MockOIDCProviderServer) handle(w http.ResponseWriter, r *http.Request) {
w.Header().Set("content-type", "application/json")
switch r.URL.Path {
case "/.well-known/openid-configuration":
fmt.Fprintln(w, openIDConfiguration)
case "/oauth2/v1/token":
m.TokenCount += 1
claims := &testIdTokenClaims{
StandardClaims: &jwt.StandardClaims{
Issuer: "http://foo.example.com",
Audience: "my_client_id",
ExpiresAt: math.MaxInt32,
},
Email: m.email,
Groups: m.groups,
CustomClaim: m.customClaim,
CustomGroupsClaim: m.customGroupsClaim,
}
tok, err := jwt.NewWithClaims(jwt.SigningMethodRS256, claims).SignedString(m.Key)
if err != nil {
panic(err)
}
fmt.Fprintf(w, `{"token_type":"bearer","access_token":"AAAAAAAAAAAA","refresh_token":"REFRESH","id_token":"%s"}`, tok)
case "/oauth2/v1/keys":
jwk := jose.JSONWebKey{KeyID: "foo", Key: m.Key.Public()}
jwks := jose.JSONWebKeySet{Keys: []jose.JSONWebKey{jwk}}
jks, _ := json.Marshal(jwks)
_, _ = w.Write(jks)
default:
panic(fmt.Sprintf("mock received unknown URL '%s'", r.URL))
}
}