• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016, Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *    * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *    * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *
15  *    * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 package com.google.auth.oauth2;
33 
34 import static org.junit.Assert.assertArrayEquals;
35 import static org.junit.Assert.assertEquals;
36 import static org.junit.Assert.assertFalse;
37 import static org.junit.Assert.assertNotSame;
38 import static org.junit.Assert.assertTrue;
39 import static org.junit.Assert.fail;
40 
41 import com.google.common.collect.ImmutableMap;
42 import java.io.IOException;
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import java.util.Collection;
46 import java.util.Collections;
47 import java.util.Date;
48 import java.util.List;
49 import java.util.Map;
50 import org.junit.Test;
51 import org.junit.runner.RunWith;
52 import org.junit.runners.JUnit4;
53 
54 @RunWith(JUnit4.class)
55 public class AppEngineCredentialsTest extends BaseSerializationTest {
56 
57   private static final String EXPECTED_ACCESS_TOKEN = "ExpectedAccessToken";
58   private static final Date EXPECTED_EXPIRATION_DATE =
59       new Date(System.currentTimeMillis() + 60L * 60L * 100L);
60   private static final byte[] EXPECTED_SIGNATURE = {0xD, 0xE, 0xA, 0xD};
61   private static final String EXPECTED_ACCOUNT = "serviceAccount";
62 
63   private static final Collection<String> SCOPES =
64       Collections.unmodifiableCollection(Arrays.asList("scope1", "scope2"));
65   private static final Collection<String> DEFAULT_SCOPES =
66       Collections.unmodifiableCollection(Arrays.asList("scope3"));
67 
68   @Test
constructor_usesAppIdentityService()69   public void constructor_usesAppIdentityService() throws IOException {
70     Collection<String> scopes = Collections.singleton("SomeScope");
71     TestAppEngineCredentials credentials = new TestAppEngineCredentials(scopes);
72     List<String> forNameArgs = credentials.getForNameArgs();
73     assertEquals(4, forNameArgs.size());
74     assertEquals(AppEngineCredentials.APP_IDENTITY_SERVICE_FACTORY_CLASS, forNameArgs.get(0));
75     assertEquals(AppEngineCredentials.APP_IDENTITY_SERVICE_CLASS, forNameArgs.get(1));
76     assertEquals(AppEngineCredentials.GET_ACCESS_TOKEN_RESULT_CLASS, forNameArgs.get(2));
77     assertEquals(AppEngineCredentials.SIGNING_RESULT_CLASS, forNameArgs.get(3));
78   }
79 
80   @Test
constructor_noAppEngineRuntime_throwsHelpfulLoadError()81   public void constructor_noAppEngineRuntime_throwsHelpfulLoadError() throws IOException {
82     try {
83       new TestAppEngineCredentialsNoSdk();
84       fail("Credential expected to fail to load if credential class not present.");
85     } catch (IOException e) {
86       String message = e.getMessage();
87       assertTrue(message.contains("Check that the App Engine SDK is deployed."));
88       assertTrue(e.getCause() instanceof ClassNotFoundException);
89       assertTrue(
90           e.getCause()
91               .getMessage()
92               .contains(AppEngineCredentials.APP_IDENTITY_SERVICE_FACTORY_CLASS));
93     }
94   }
95 
96   @Test
refreshAccessToken_sameAs()97   public void refreshAccessToken_sameAs() throws IOException {
98     TestAppEngineCredentials credentials = new TestAppEngineCredentials(SCOPES);
99     AccessToken accessToken = credentials.refreshAccessToken();
100     assertEquals(EXPECTED_ACCESS_TOKEN, accessToken.getTokenValue());
101     assertEquals(EXPECTED_EXPIRATION_DATE, accessToken.getExpirationTime());
102   }
103 
104   @Test
getAccount_sameAs()105   public void getAccount_sameAs() throws IOException {
106     TestAppEngineCredentials credentials = new TestAppEngineCredentials(SCOPES);
107     assertEquals(EXPECTED_ACCOUNT, credentials.getAccount());
108   }
109 
110   @Test
sign_sameAs()111   public void sign_sameAs() throws IOException {
112     TestAppEngineCredentials credentials = new TestAppEngineCredentials(SCOPES);
113     assertArrayEquals(EXPECTED_SIGNATURE, credentials.sign("Bytes to sign".getBytes()));
114   }
115 
116   @Test
createScoped_clonesWithScopes()117   public void createScoped_clonesWithScopes() throws IOException {
118     TestAppEngineCredentials credentials = new TestAppEngineCredentials(null);
119     assertTrue(credentials.createScopedRequired());
120     try {
121       credentials.refreshAccessToken();
122       fail("Should not be able to use credential without scopes.");
123     } catch (Exception expected) {
124       // Expected
125     }
126 
127     GoogleCredentials scopedCredentials = credentials.createScoped(SCOPES);
128     assertNotSame(credentials, scopedCredentials);
129 
130     AccessToken accessToken = scopedCredentials.refreshAccessToken();
131     assertEquals(EXPECTED_ACCESS_TOKEN, accessToken.getTokenValue());
132     assertEquals(EXPECTED_EXPIRATION_DATE, accessToken.getExpirationTime());
133   }
134 
135   @Test
createScoped_defaultScopes()136   public void createScoped_defaultScopes() throws IOException {
137     TestAppEngineCredentials credentials = new TestAppEngineCredentials(null);
138     assertTrue(credentials.createScopedRequired());
139 
140     GoogleCredentials newCredentials = credentials.createScoped(null, DEFAULT_SCOPES);
141     assertFalse(newCredentials.createScopedRequired());
142 
143     newCredentials = credentials.createScoped(SCOPES, null);
144     assertFalse(newCredentials.createScopedRequired());
145 
146     newCredentials = credentials.createScoped(SCOPES, DEFAULT_SCOPES);
147     assertFalse(newCredentials.createScopedRequired());
148 
149     AccessToken accessToken = newCredentials.refreshAccessToken();
150     assertEquals(EXPECTED_ACCESS_TOKEN, accessToken.getTokenValue());
151     assertEquals(EXPECTED_EXPIRATION_DATE, accessToken.getExpirationTime());
152   }
153 
154   @Test
equals_true()155   public void equals_true() throws IOException {
156     GoogleCredentials credentials = new TestAppEngineCredentials(SCOPES);
157     GoogleCredentials otherCredentials = new TestAppEngineCredentials(SCOPES);
158     assertTrue(credentials.equals(credentials));
159     assertTrue(credentials.equals(otherCredentials));
160     assertTrue(otherCredentials.equals(credentials));
161   }
162 
163   @Test
equals_false_scopes()164   public void equals_false_scopes() throws IOException {
165     final Collection<String> emptyScopes = Collections.emptyList();
166     Collection<String> scopes = Collections.singleton("SomeScope");
167     AppEngineCredentials credentials = new TestAppEngineCredentials(emptyScopes);
168     AppEngineCredentials otherCredentials = new TestAppEngineCredentials(scopes);
169     assertFalse(credentials.equals(otherCredentials));
170     assertFalse(otherCredentials.equals(credentials));
171   }
172 
173   @Test
toString_containsFields()174   public void toString_containsFields() throws IOException {
175     String expectedToString =
176         String.format(
177             "TestAppEngineCredentials{scopes=[%s], scopesRequired=%b}", "SomeScope", false);
178     Collection<String> scopes = Collections.singleton("SomeScope");
179     AppEngineCredentials credentials = new TestAppEngineCredentials(scopes);
180     assertEquals(expectedToString, credentials.toString());
181   }
182 
183   @Test
hashCode_equals()184   public void hashCode_equals() throws IOException {
185     AppEngineCredentials credentials = new TestAppEngineCredentials(SCOPES);
186     assertEquals(credentials.hashCode(), credentials.hashCode());
187   }
188 
189   @Test
serialize()190   public void serialize() throws IOException, ClassNotFoundException {
191     Collection<String> scopes = Collections.singleton("SomeScope");
192     AppEngineCredentials credentials = new TestAppEngineCredentials(scopes);
193     GoogleCredentials deserializedCredentials = serializeAndDeserialize(credentials);
194     assertEquals(credentials, deserializedCredentials);
195     assertEquals(credentials.hashCode(), deserializedCredentials.hashCode());
196     assertEquals(credentials.toString(), deserializedCredentials.toString());
197   }
198 
199   private static class TestSigningResult {
200 
201     private final byte[] signature;
202 
TestSigningResult(byte[] signature)203     TestSigningResult(byte[] signature) {
204       this.signature = signature;
205     }
206 
getSignature()207     public byte[] getSignature() {
208       return this.signature;
209     }
210   }
211 
212   private static class TestAppIdentityServiceFactory {
213 
getAppIdentityService()214     public static TestAppIdentityService getAppIdentityService() {
215       return new TestAppIdentityService();
216     }
217   }
218 
219   private static class TestAppIdentityService {
220 
getAccessToken(Iterable<String> scopes)221     public TestGetAccessTokenResult getAccessToken(Iterable<String> scopes) {
222       return new TestGetAccessTokenResult(EXPECTED_ACCESS_TOKEN, EXPECTED_EXPIRATION_DATE);
223     }
224 
getServiceAccountName()225     public String getServiceAccountName() {
226       return EXPECTED_ACCOUNT;
227     }
228 
signForApp(byte[] toSign)229     public TestSigningResult signForApp(byte[] toSign) {
230       return new TestSigningResult(EXPECTED_SIGNATURE);
231     }
232   }
233 
234   private static class TestGetAccessTokenResult {
235 
236     private final String accessToken;
237     private final Date expirationTime;
238 
TestGetAccessTokenResult(String accessToken, Date expirationTime)239     TestGetAccessTokenResult(String accessToken, Date expirationTime) {
240       this.accessToken = accessToken;
241       this.expirationTime = expirationTime;
242     }
243 
getAccessToken()244     public String getAccessToken() {
245       return this.accessToken;
246     }
247 
getExpirationTime()248     public Date getExpirationTime() {
249       return this.expirationTime;
250     }
251   }
252 
253   private static class TestAppEngineCredentials extends AppEngineCredentials {
254 
255     private static final long serialVersionUID = -5191475572296306231L;
256 
257     private static final Map<String, Class<?>> TYPES =
258         ImmutableMap.of(
259             AppEngineCredentials.APP_IDENTITY_SERVICE_FACTORY_CLASS,
260             TestAppIdentityServiceFactory.class,
261             AppEngineCredentials.APP_IDENTITY_SERVICE_CLASS,
262             TestAppIdentityService.class,
263             AppEngineCredentials.GET_ACCESS_TOKEN_RESULT_CLASS,
264             TestGetAccessTokenResult.class,
265             AppEngineCredentials.SIGNING_RESULT_CLASS,
266             TestSigningResult.class);
267     private List<String> forNameArgs;
268 
TestAppEngineCredentials(Collection<String> scopes)269     TestAppEngineCredentials(Collection<String> scopes) throws IOException {
270       super(scopes, null);
271     }
272 
TestAppEngineCredentials(Collection<String> scopes, Collection<String> defaultScopes)273     TestAppEngineCredentials(Collection<String> scopes, Collection<String> defaultScopes)
274         throws IOException {
275       super(scopes, defaultScopes);
276     }
277 
278     @Override
forName(String className)279     Class<?> forName(String className) throws ClassNotFoundException {
280       if (forNameArgs == null) {
281         forNameArgs = new ArrayList<>();
282       }
283       forNameArgs.add(className);
284       Class<?> lookup = TYPES.get(className);
285       if (lookup != null) {
286         return lookup;
287       }
288       throw new ClassNotFoundException(className);
289     }
290 
getForNameArgs()291     List<String> getForNameArgs() {
292       return forNameArgs;
293     }
294   }
295 
296   private static class TestAppEngineCredentialsNoSdk extends AppEngineCredentials {
297 
298     private static final long serialVersionUID = -8987103249265111274L;
299 
TestAppEngineCredentialsNoSdk()300     TestAppEngineCredentialsNoSdk() throws IOException {
301       super(null, null);
302     }
303 
304     @Override
forName(String className)305     Class<?> forName(String className) throws ClassNotFoundException {
306       throw new ClassNotFoundException(className);
307     }
308   }
309 }
310