1// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package google
6
7import (
8	"bytes"
9	"crypto/rand"
10	"crypto/rsa"
11	"crypto/x509"
12	"encoding/base64"
13	"encoding/json"
14	"encoding/pem"
15	"strings"
16	"testing"
17	"time"
18
19	"golang.org/x/oauth2/jws"
20)
21
22func TestJWTAccessTokenSourceFromJSON(t *testing.T) {
23	// Generate a key we can use in the test data.
24	privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
25	if err != nil {
26		t.Fatal(err)
27	}
28
29	// Encode the key and substitute into our example JSON.
30	enc := pem.EncodeToMemory(&pem.Block{
31		Type:  "PRIVATE KEY",
32		Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
33	})
34	enc, err = json.Marshal(string(enc))
35	if err != nil {
36		t.Fatalf("json.Marshal: %v", err)
37	}
38	jsonKey := bytes.Replace(jwtJSONKey, []byte(`"super secret key"`), enc, 1)
39
40	ts, err := JWTAccessTokenSourceFromJSON(jsonKey, "audience")
41	if err != nil {
42		t.Fatalf("JWTAccessTokenSourceFromJSON: %v\nJSON: %s", err, string(jsonKey))
43	}
44
45	tok, err := ts.Token()
46	if err != nil {
47		t.Fatalf("Token: %v", err)
48	}
49
50	if got, want := tok.TokenType, "Bearer"; got != want {
51		t.Errorf("TokenType = %q, want %q", got, want)
52	}
53	if got := tok.Expiry; tok.Expiry.Before(time.Now()) {
54		t.Errorf("Expiry = %v, should not be expired", got)
55	}
56
57	err = jws.Verify(tok.AccessToken, &privateKey.PublicKey)
58	if err != nil {
59		t.Errorf("jws.Verify on AccessToken: %v", err)
60	}
61
62	claim, err := jws.Decode(tok.AccessToken)
63	if err != nil {
64		t.Fatalf("jws.Decode on AccessToken: %v", err)
65	}
66
67	if got, want := claim.Iss, "gopher@developer.gserviceaccount.com"; got != want {
68		t.Errorf("Iss = %q, want %q", got, want)
69	}
70	if got, want := claim.Sub, "gopher@developer.gserviceaccount.com"; got != want {
71		t.Errorf("Sub = %q, want %q", got, want)
72	}
73	if got, want := claim.Aud, "audience"; got != want {
74		t.Errorf("Aud = %q, want %q", got, want)
75	}
76
77	// Finally, check the header private key.
78	parts := strings.Split(tok.AccessToken, ".")
79	hdrJSON, err := base64.RawURLEncoding.DecodeString(parts[0])
80	if err != nil {
81		t.Fatalf("base64 DecodeString: %v\nString: %q", err, parts[0])
82	}
83	var hdr jws.Header
84	if err := json.Unmarshal([]byte(hdrJSON), &hdr); err != nil {
85		t.Fatalf("json.Unmarshal: %v (%q)", err, hdrJSON)
86	}
87
88	if got, want := hdr.KeyID, "268f54e43a1af97cfc71731688434f45aca15c8b"; got != want {
89		t.Errorf("Header KeyID = %q, want %q", got, want)
90	}
91}
92