Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(425)

Side by Side Diff: remoting/android/java/src/org/chromium/chromoting/ThirdPartyTokenFetcher.java

Issue 348433002: Verify the host-supplied URL matches the domain's allowed URL patterns (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Lambros' feedbacks Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/android/java/src/org/chromium/chromoting/HostListLoader.java ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 /** Verifies the host-supplied URL matches the domain's allowed URL patterns . */
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
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 }
OLDNEW
« no previous file with comments | « remoting/android/java/src/org/chromium/chromoting/HostListLoader.java ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698