15 "github.com/dgrijalva/jwt-go"
16 . "github.com/onsi/gomega"
17 "github.com/stretchr/testify/assert"
18 "gopkg.in/square/go-jose.v2"
21type MyKeyData struct {
22 PubKey crypto.PublicKey
23 PrivKey *rsa.PrivateKey
24 PubJWK jose.JSONWebKey
27func newLoginGovServer(body []byte) (*url.URL, *httptest.Server) {
28 s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
31 u, _ := url.Parse(s.URL)
35func newLoginGovProvider() (l *LoginGovProvider, serverKey *MyKeyData, err error) {
36 key, err := rsa.GenerateKey(rand.Reader, 2048)
40 serverKey = &MyKeyData{
43 PubJWK: jose.JSONWebKey{
46 Algorithm: string(jose.RS256),
51 privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
56 l = NewLoginGovProvider(
60 RedeemURL: &url.URL{},
61 ProfileURL: &url.URL{},
62 ValidateURL: &url.URL{},
69func TestNewLoginGovProvider(t *testing.T) {
72 // Test that defaults are set when calling for a new provider with nothing set
73 providerData := NewLoginGovProvider(&ProviderData{}).Data()
74 g.Expect(providerData.ProviderName).To(Equal("login.gov"))
75 g.Expect(providerData.LoginURL.String()).To(Equal("https://secure.login.gov/openid_connect/authorize"))
76 g.Expect(providerData.RedeemURL.String()).To(Equal("https://secure.login.gov/api/openid_connect/token"))
77 g.Expect(providerData.ProfileURL.String()).To(Equal("https://secure.login.gov/api/openid_connect/userinfo"))
78 g.Expect(providerData.ValidateURL.String()).To(Equal(""))
79 g.Expect(providerData.Scope).To(Equal("email openid"))
82func TestLoginGovProviderOverrides(t *testing.T) {
83 p := NewLoginGovProvider(
92 Path: "/oauth/token"},
96 Path: "/oauth/profile"},
98 assert.NotEqual(t, nil, p)
99 assert.Equal(t, "login.gov", p.Data().ProviderName)
100 assert.Equal(t, "https://example.com/oauth/auth",
101 p.Data().LoginURL.String())
102 assert.Equal(t, "https://example.com/oauth/token",
103 p.Data().RedeemURL.String())
104 assert.Equal(t, "https://example.com/oauth/profile",
105 p.Data().ProfileURL.String())
106 assert.Equal(t, "profile", p.Data().Scope)
109func TestLoginGovProviderSessionData(t *testing.T) {
110 p, serverkey, err := newLoginGovProvider()
111 assert.NotEqual(t, nil, p)
112 assert.NoError(t, err)
114 // Set up the redeem endpoint here
115 type loginGovRedeemResponse struct {
116 AccessToken string `json:"access_token"`
117 TokenType string `json:"token_type"`
118 ExpiresIn int64 `json:"expires_in"`
119 IDToken string `json:"id_token"`
121 expiresIn := int64(60)
122 type MyCustomClaims struct {
123 Acr string `json:"acr"`
124 Nonce string `json:"nonce"`
125 Email string `json:"email"`
126 EmailVerified bool `json:"email_verified"`
127 GivenName string `json:"given_name"`
128 FamilyName string `json:"family_name"`
129 Birthdate string `json:"birthdate"`
130 AtHash string `json:"at_hash"`
131 CHash string `json:"c_hash"`
134 claims := MyCustomClaims{
135 "http://idmanagement.gov/ns/assurance/loa/1",
137 "timothy.spencer@gsa.gov",
145 Audience: "Audience",
146 ExpiresAt: time.Now().Unix() + expiresIn,
148 IssuedAt: time.Now().Unix(),
149 Issuer: "https://idp.int.login.gov",
150 NotBefore: time.Now().Unix() - 1,
151 Subject: "b2d2d115-1d7e-4579-b9d6-f8e84f4f56ca",
154 idtoken := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
155 signedidtoken, err := idtoken.SignedString(serverkey.PrivKey)
156 assert.NoError(t, err)
157 body, err := json.Marshal(loginGovRedeemResponse{
158 AccessToken: "a1234",
160 ExpiresIn: expiresIn,
161 IDToken: signedidtoken,
163 assert.NoError(t, err)
164 var server *httptest.Server
165 p.RedeemURL, server = newLoginGovServer(body)
168 // Set up the user endpoint here
169 type loginGovUserResponse struct {
170 Email string `json:"email"`
171 EmailVerified bool `json:"email_verified"`
172 Subject string `json:"sub"`
174 userbody, err := json.Marshal(loginGovUserResponse{
175 Email: "timothy.spencer@gsa.gov",
177 Subject: "b2d2d115-1d7e-4579-b9d6-f8e84f4f56ca",
179 assert.NoError(t, err)
180 var userserver *httptest.Server
181 p.ProfileURL, userserver = newLoginGovServer(userbody)
182 defer userserver.Close()
184 // Set up the PubJWKURL endpoint here used to verify the JWT
185 var pubkeys jose.JSONWebKeySet
186 pubkeys.Keys = append(pubkeys.Keys, serverkey.PubJWK)
187 pubjwkbody, err := json.Marshal(pubkeys)
188 assert.NoError(t, err)
189 var pubjwkserver *httptest.Server
190 p.PubJWKURL, pubjwkserver = newLoginGovServer(pubjwkbody)
191 defer pubjwkserver.Close()
193 session, err := p.Redeem(context.Background(), "http://redirect/", "code1234")
194 assert.NoError(t, err)
195 assert.NotEqual(t, session, nil)
196 assert.Equal(t, "timothy.spencer@gsa.gov", session.Email)
197 assert.Equal(t, "a1234", session.AccessToken)
199 // The test ought to run in under 2 seconds. If not, you may need to bump this up.
200 assert.InDelta(t, session.ExpiresOn.Unix(), time.Now().Unix()+expiresIn, 2)
203func TestLoginGovProviderBadNonce(t *testing.T) {
204 p, serverkey, err := newLoginGovProvider()
205 assert.NotEqual(t, nil, p)
206 assert.NoError(t, err)
208 // Set up the redeem endpoint here
209 type loginGovRedeemResponse struct {
210 AccessToken string `json:"access_token"`
211 TokenType string `json:"token_type"`
212 ExpiresIn int64 `json:"expires_in"`
213 IDToken string `json:"id_token"`
215 expiresIn := int64(60)
216 type MyCustomClaims struct {
217 Acr string `json:"acr"`
218 Nonce string `json:"nonce"`
219 Email string `json:"email"`
220 EmailVerified bool `json:"email_verified"`
221 GivenName string `json:"given_name"`
222 FamilyName string `json:"family_name"`
223 Birthdate string `json:"birthdate"`
224 AtHash string `json:"at_hash"`
225 CHash string `json:"c_hash"`
228 claims := MyCustomClaims{
229 "http://idmanagement.gov/ns/assurance/loa/1",
231 "timothy.spencer@gsa.gov",
239 Audience: "Audience",
240 ExpiresAt: time.Now().Unix() + expiresIn,
242 IssuedAt: time.Now().Unix(),
243 Issuer: "https://idp.int.login.gov",
244 NotBefore: time.Now().Unix() - 1,
245 Subject: "b2d2d115-1d7e-4579-b9d6-f8e84f4f56ca",
248 idtoken := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
249 signedidtoken, err := idtoken.SignedString(serverkey.PrivKey)
250 assert.NoError(t, err)
251 body, err := json.Marshal(loginGovRedeemResponse{
252 AccessToken: "a1234",
254 ExpiresIn: expiresIn,
255 IDToken: signedidtoken,
257 assert.NoError(t, err)
258 var server *httptest.Server
259 p.RedeemURL, server = newLoginGovServer(body)
262 // Set up the user endpoint here
263 type loginGovUserResponse struct {
264 Email string `json:"email"`
265 EmailVerified bool `json:"email_verified"`
266 Subject string `json:"sub"`
268 userbody, err := json.Marshal(loginGovUserResponse{
269 Email: "timothy.spencer@gsa.gov",
271 Subject: "b2d2d115-1d7e-4579-b9d6-f8e84f4f56ca",
273 assert.NoError(t, err)
274 var userserver *httptest.Server
275 p.ProfileURL, userserver = newLoginGovServer(userbody)
276 defer userserver.Close()
278 // Set up the PubJWKURL endpoint here used to verify the JWT
279 var pubkeys jose.JSONWebKeySet
280 pubkeys.Keys = append(pubkeys.Keys, serverkey.PubJWK)
281 pubjwkbody, err := json.Marshal(pubkeys)
282 assert.NoError(t, err)
283 var pubjwkserver *httptest.Server
284 p.PubJWKURL, pubjwkserver = newLoginGovServer(pubjwkbody)
285 defer pubjwkserver.Close()
287 _, err = p.Redeem(context.Background(), "http://redirect/", "code1234")
289 // The "badfakenonce" in the idtoken above should cause this to error out
293func TestLoginGovProviderGetLoginURL(t *testing.T) {
294 p, _, _ := newLoginGovProvider()
295 result := p.GetLoginURL("http://redirect/", "")
296 assert.Contains(t, result, "acr_values="+url.QueryEscape("http://idmanagement.gov/ns/assurance/loa/1"))
297 assert.Contains(t, result, "nonce=fakenonce")
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list