OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chromoting; | 5 package org.chromium.chromoting; |
6 | 6 |
7 import android.app.Activity; | 7 import android.app.Activity; |
8 import android.content.ActivityNotFoundException; | 8 import android.content.ActivityNotFoundException; |
9 import android.content.ComponentName; | 9 import android.content.ComponentName; |
10 import android.content.Intent; | 10 import android.content.Intent; |
11 import android.content.pm.PackageManager; | 11 import android.content.pm.PackageManager; |
12 import android.net.Uri; | 12 import android.net.Uri; |
13 import android.text.TextUtils; | |
13 import android.util.Base64; | 14 import android.util.Base64; |
14 import android.util.Log; | 15 import android.util.Log; |
15 | 16 |
16 import java.security.SecureRandom; | 17 import java.security.SecureRandom; |
18 import java.util.ArrayList; | |
17 import java.util.HashMap; | 19 import java.util.HashMap; |
18 | 20 |
19 /** | 21 /** |
20 * This class is responsible for fetching a third party token from the user usin g the OAuth2 | 22 * This class is responsible for fetching a third party token from the user usin g the OAuth2 |
21 * implicit flow. It pops up a third party login page located at |tokenurl|. I t relies on the | 23 * implicit flow. It pops up a third party login page located at |tokenurl|. I t relies on the |
22 * |ThirdPartyTokenFetcher$OAuthRedirectActivity| to intercept the access token from the redirect at | 24 * |ThirdPartyTokenFetcher$OAuthRedirectActivity| to intercept the access token from the redirect at |
23 * |REDIRECT_URI_SCHEME|://|REDIRECT_URI_HOST| upon successful login. | 25 * |REDIRECT_URI_SCHEME|://|REDIRECT_URI_HOST| upon successful login. |
24 */ | 26 */ |
25 public class ThirdPartyTokenFetcher { | 27 public class ThirdPartyTokenFetcher { |
26 /** Callback for receiving the token. */ | 28 /** Callback for receiving the token. */ |
(...skipping 17 matching lines...) Expand all Loading... | |
44 private Activity mContext; | 46 private Activity mContext; |
45 | 47 |
46 /** | 48 /** |
47 * An opaque value used by the client to maintain state between the request and callback. The | 49 * An opaque value used by the client to maintain state between the request and callback. The |
48 * authorization server includes this value when redirecting the user-agent back to the client. | 50 * authorization server includes this value when redirecting the user-agent back to the client. |
49 * The parameter is used for preventing cross-site request forgery. See | 51 * The parameter is used for preventing cross-site request forgery. See |
50 * http://tools.ietf.org/html/rfc6749#section-10.12. | 52 * http://tools.ietf.org/html/rfc6749#section-10.12. |
51 */ | 53 */ |
52 private final String mState; | 54 private final String mState; |
53 | 55 |
54 /** URL of the third party login page. */ | 56 private final Callback mCallback; |
55 private final String mTokenUrl; | |
56 | 57 |
57 /** The client identifier. See http://tools.ietf.org/html/rfc6749#section-2. 2. */ | 58 /** The list of TokenUrls allowed by the domain. */ |
58 private final String mClientId; | 59 private final ArrayList<String> mTokenUrlPatterns; |
59 | |
60 /** The scope of access request. See http://tools.ietf.org/html/rfc6749#sect ion-3.3. */ | |
61 private final String mScope; | |
62 | |
63 private final Callback mCallback; | |
64 | 60 |
65 private final String mRedirectUriScheme; | 61 private final String mRedirectUriScheme; |
66 | 62 |
67 private final String mRedirectUri; | 63 private final String mRedirectUri; |
68 | 64 |
69 public ThirdPartyTokenFetcher(Activity context, | 65 public ThirdPartyTokenFetcher(Activity context, |
70 String tokenUrl, | 66 ArrayList<String> tokenUrlPatterns, |
71 String clientId, | |
72 String scope, | |
73 Callback callback) { | 67 Callback callback) { |
74 this.mContext = context; | 68 this.mContext = context; |
75 this.mTokenUrl = tokenUrl; | |
76 this.mClientId = clientId; | |
77 this.mState = generateXsrfToken(); | 69 this.mState = generateXsrfToken(); |
78 this.mScope = scope; | |
79 this.mCallback = callback; | 70 this.mCallback = callback; |
71 this.mTokenUrlPatterns = tokenUrlPatterns; | |
80 | 72 |
81 this.mRedirectUriScheme = context.getApplicationContext().getPackageName (); | 73 this.mRedirectUriScheme = context.getApplicationContext().getPackageName (); |
82 this.mRedirectUri = mRedirectUriScheme + "://" + REDIRECT_URI_HOST; | 74 this.mRedirectUri = mRedirectUriScheme + "://" + REDIRECT_URI_HOST; |
83 } | 75 } |
84 | 76 |
85 public void fetchToken() { | 77 /** |
86 Uri.Builder uriBuilder = Uri.parse(mTokenUrl).buildUpon(); | 78 * @param tokenUrl URL of the third party login page. |
87 uriBuilder.appendQueryParameter("redirect_uri", this.mRedirectUri); | 79 * @param clientId The client identifier. See http://tools.ietf.org/html/rfc 6749#section-2.2. |
88 uriBuilder.appendQueryParameter("scope", mScope); | 80 * @param scope The scope of access request. See http://tools.ietf.org/html/ rfc6749#section-3.3. |
89 uriBuilder.appendQueryParameter("client_id", mClientId); | 81 */ |
90 uriBuilder.appendQueryParameter("state", mState); | 82 public void fetchToken(String tokenUrl, String clientId, String scope) { |
91 uriBuilder.appendQueryParameter("response_type", RESPONSE_TYPE); | 83 if (!isValidTokenUrl(tokenUrl)) { |
84 failFetchToken( | |
85 "Token URL does not match the domain\'s allowed URL patterns ." + | |
86 " URL: " + tokenUrl + | |
87 ", patterns: " + TextUtils.join(",", this.mTokenUrlPatterns) ); | |
88 return; | |
89 } | |
92 | 90 |
93 Uri uri = uriBuilder.build(); | 91 Uri uri = buildRequestUri(tokenUrl, clientId, scope); |
94 Intent intent = new Intent(Intent.ACTION_VIEW, uri); | 92 Intent intent = new Intent(Intent.ACTION_VIEW, uri); |
95 Log.i("ThirdPartyAuth", "fetchToken() url:" + uri); | 93 Log.i("ThirdPartyAuth", "fetchToken() url:" + uri); |
96 OAuthRedirectActivity.setEnabled(mContext, true); | 94 OAuthRedirectActivity.setEnabled(mContext, true); |
97 | 95 |
98 try { | 96 try { |
99 mContext.startActivity(intent); | 97 mContext.startActivity(intent); |
100 } catch (ActivityNotFoundException e) { | 98 } catch (ActivityNotFoundException e) { |
101 failFetchToken("No browser is installed to open the third party auth entication page."); | 99 failFetchToken("No browser is installed to open the third party auth entication page."); |
102 } | 100 } |
103 } | 101 } |
104 | 102 |
103 private Uri buildRequestUri(String tokenUrl, String clientId, String scope) { | |
104 Uri.Builder uriBuilder = Uri.parse(tokenUrl).buildUpon(); | |
105 uriBuilder.appendQueryParameter("redirect_uri", this.mRedirectUri); | |
106 uriBuilder.appendQueryParameter("scope", scope); | |
107 uriBuilder.appendQueryParameter("client_id", clientId); | |
108 uriBuilder.appendQueryParameter("state", mState); | |
109 uriBuilder.appendQueryParameter("response_type", RESPONSE_TYPE); | |
110 | |
111 return uriBuilder.build(); | |
112 } | |
113 | |
114 /** Verify the host-supplied URL matches the domain's allowed URL patterns. */ | |
Lambros
2014/06/18 23:29:06
nit: s/Verify/Verifies. Function comments are desc
kelvinp
2014/06/19 01:03:50
Done.
| |
115 private boolean isValidTokenUrl(String tokenUrl) { | |
116 for (String pattern : mTokenUrlPatterns) { | |
117 if (tokenUrl.matches(pattern)) { | |
118 return true; | |
119 } | |
120 } | |
121 return false; | |
122 } | |
123 | |
105 private boolean isValidIntent(Intent intent) { | 124 private boolean isValidIntent(Intent intent) { |
106 assert intent != null; | 125 assert intent != null; |
107 | 126 |
108 String action = intent.getAction(); | 127 String action = intent.getAction(); |
109 | 128 |
110 Uri data = intent.getData(); | 129 Uri data = intent.getData(); |
111 if (data != null) { | 130 if (data != null) { |
112 return Intent.ACTION_VIEW.equals(action) && | 131 return Intent.ACTION_VIEW.equals(action) && |
113 this.mRedirectUriScheme.equals(data.getScheme()) && | 132 this.mRedirectUriScheme.equals(data.getScheme()) && |
114 REDIRECT_URI_HOST.equals(data.getHost()); | 133 REDIRECT_URI_HOST.equals(data.getHost()); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
216 ComponentName component = new ComponentName( | 235 ComponentName component = new ComponentName( |
217 context.getApplicationContext(), | 236 context.getApplicationContext(), |
218 ThirdPartyTokenFetcher.OAuthRedirectActivity.class); | 237 ThirdPartyTokenFetcher.OAuthRedirectActivity.class); |
219 context.getPackageManager().setComponentEnabledSetting( | 238 context.getPackageManager().setComponentEnabledSetting( |
220 component, | 239 component, |
221 enabledState, | 240 enabledState, |
222 PackageManager.DONT_KILL_APP); | 241 PackageManager.DONT_KILL_APP); |
223 } | 242 } |
224 } | 243 } |
225 } | 244 } |
OLD | NEW |