-
Notifications
You must be signed in to change notification settings - Fork 347
/
Copy pathAuthenticationActivity.cs
222 lines (190 loc) · 7.25 KB
/
AuthenticationActivity.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
#if __ANDROID_29__
using AndroidX.Browser.CustomTabs;
#else
using Android.Support.CustomTabs;
#endif
using Microsoft.Identity.Client.Internal;
using Microsoft.Identity.Client.OAuth2;
using Uri = Android.Net.Uri;
namespace Microsoft.Identity.Client.Platforms.Android.SystemWebview
{
/// <summary>
/// </summary>
[Activity(Name = "microsoft.identity.client.AuthenticationActivity")]
[global::Android.Runtime.Preserve(AllMembers = true)]
internal class AuthenticationActivity : Activity
{
internal static RequestContext RequestContext { get; set; }
/// <summary>
/// Default Constructor
/// </summary>
public AuthenticationActivity()
{ }
// this is used to check if anything can open custom tabs.
// Must use the classic support. Leaving the reference AndroidX intent
#if __ANDROID_29__
private readonly string _customTabsServiceAction =
"androidx.browser.customtabs.action.CustomTabsService";
#else
private readonly string _customTabsServiceAction =
"android.support.customtabs.action.CustomTabsService";
#endif
private string _requestUrl;
private int _requestId;
private bool _restarted;
/// <summary>
/// </summary>
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// If activity is killed by the OS, savedInstance will be the saved bundle.
if (bundle != null)
{
_restarted = true;
return;
}
if (Intent == null)
{
SendError(
MsalError.UnresolvableIntentError,
"Received null data intent from caller");
return;
}
_requestUrl = Intent.GetStringExtra(AndroidConstants.RequestUrlKey);
_requestId = Intent.GetIntExtra(AndroidConstants.RequestId, 0);
if (string.IsNullOrEmpty(_requestUrl))
{
SendError(MsalError.InvalidRequest, "Request url is not set on the intent");
}
}
/// <summary>
///
/// </summary>
/// <param name="intent"></param>
protected override void OnNewIntent(Intent intent)
{
base.OnNewIntent(intent);
string url = intent.GetStringExtra(AndroidConstants.CustomTabRedirect);
Intent resultIntent = new Intent();
resultIntent.PutExtra(AndroidConstants.AuthorizationFinalUrl, url);
ReturnToCaller(AndroidConstants.AuthCodeReceived,
resultIntent);
}
/// <summary>
///
/// </summary>
protected override void OnResume()
{
base.OnResume();
if (_restarted)
{
cancelRequest();
return;
}
_restarted = true;
string chromePackageWithCustomTabSupport = GetChromePackageWithCustomTabSupport(ApplicationContext);
if (string.IsNullOrEmpty(chromePackageWithCustomTabSupport))
{
Intent browserIntent = new Intent(Intent.ActionView, Uri.Parse(_requestUrl));
browserIntent.AddCategory(Intent.CategoryBrowsable);
RequestContext.Logger.Warning(
"Browser with custom tabs package not available. " +
"Launching with alternate browser. See https://aka.ms/msal-net-system-browsers for details.");
try
{
StartActivity(browserIntent);
}
catch (ActivityNotFoundException ex)
{
throw new MsalClientException(
MsalError.AndroidActivityNotFound,
MsalErrorMessage.AndroidActivityNotFound, ex);
}
}
else
{
RequestContext.Logger.Info(
string.Format(
CultureInfo.CurrentCulture,
"Browser with custom tabs package available. Using {0}. ",
chromePackageWithCustomTabSupport));
CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder().Build();
customTabsIntent.Intent.SetPackage(chromePackageWithCustomTabSupport);
customTabsIntent.LaunchUrl(this, Uri.Parse(_requestUrl));
}
}
/// <summary>
///
/// </summary>
/// <param name="outState"></param>
protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
outState.PutString(AndroidConstants.RequestUrlKey, _requestUrl);
}
/**
* Cancels the auth request.
*/
private void cancelRequest()
{
ReturnToCaller(AndroidConstants.Cancel, new Intent());
}
/**
* Return the error back to caller.
* @param resultCode The result code to return back.
* @param data {@link Intent} contains the detailed result.
*/
private void ReturnToCaller(int resultCode, Intent data)
{
data.PutExtra(AndroidConstants.RequestId, _requestId);
SetResult((Result)resultCode, data);
Finish();
}
/**
* Send error back to caller with the error description.
* @param errorCode The error code to send back.
* @param errorDescription The error description to send back.
*/
private void SendError(string errorCode, string errorDescription)
{
Intent errorIntent = new Intent();
errorIntent.PutExtra(OAuth2ResponseBaseClaim.Error, errorCode);
errorIntent.PutExtra(OAuth2ResponseBaseClaim.ErrorDescription, errorDescription);
ReturnToCaller(AndroidConstants.AuthCodeError, errorIntent);
}
private string GetChromePackageWithCustomTabSupport(Context context)
{
if (context.PackageManager == null)
{
return null;
}
Intent customTabServiceIntent = new Intent(_customTabsServiceAction);
IEnumerable<ResolveInfo> resolveInfoListWithCustomTabs = context.PackageManager.QueryIntentServices(
customTabServiceIntent, PackageInfoFlags.MatchAll);
// queryIntentServices could return null or an empty list if no matching service existed.
if (resolveInfoListWithCustomTabs == null || !resolveInfoListWithCustomTabs.Any())
{
return null;
}
foreach (ResolveInfo resolveInfo in resolveInfoListWithCustomTabs)
{
ServiceInfo serviceInfo = resolveInfo.ServiceInfo;
if (serviceInfo != null)
{
return serviceInfo.PackageName;
}
}
return null;
}
}
}