-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
WebAuthenticatorResult.shared.cs
146 lines (129 loc) · 4.98 KB
/
WebAuthenticatorResult.shared.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
using System;
using System.Collections.Generic;
using Microsoft.Maui.ApplicationModel;
namespace Microsoft.Maui.Authentication
{
/// <summary>
/// Represents a Web Authenticator Result object parsed from the callback Url.
/// </summary>
/// <remarks>
/// All of the query string or url fragment properties are parsed into a dictionary and can be accessed by their key.
/// </remarks>
public class WebAuthenticatorResult
{
/// <summary>
/// Initializes a new instance of the <see cref="WebAuthenticatorResult"/> class.
/// </summary>
public WebAuthenticatorResult()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="WebAuthenticatorResult"/> class by parsing a URI's query string parameters.
/// </summary>
/// <param name="uri">The callback uri that was used to end the authentication sequence.</param>
public WebAuthenticatorResult(Uri uri) : this(uri, null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="WebAuthenticatorResult"/> class by parsing a URI's query string parameters.
/// </summary>
/// <remarks>
/// If the responseDecoder is non-null, then it is used to decode the fragment or query string
/// returned by the authorization service. Otherwise, a default response decoder is used.
/// </remarks>
/// <param name="uri">The callback uri that was used to end the authentication sequence.</param>
/// <param name="responseDecoder">The decoder that can be used to decode the callback uri.</param>
public WebAuthenticatorResult(Uri uri, IWebAuthenticatorResponseDecoder responseDecoder)
{
CallbackUri = uri;
var properties = responseDecoder?.DecodeResponse(uri) ?? WebUtils.ParseQueryString(uri);
foreach (var kvp in properties)
{
Properties[kvp.Key] = kvp.Value;
}
}
/// <summary>
/// Create a new instance from an existing dictionary.
/// </summary>
/// <param name="properties">The dictionary of properties to incorporate.</param>
public WebAuthenticatorResult(IDictionary<string, string> properties)
{
foreach (var kvp in properties)
Properties[kvp.Key] = kvp.Value;
}
/// <summary>
/// The uri that was used to call back with the access token.
/// </summary>
/// <value>
/// The value of the callback URI, including the fragment or query string bearing
/// the access token and associated information.
/// </value>
public Uri CallbackUri { get; }
/// <summary>
/// The timestamp when the class was instantiated, which usually corresponds with the parsed result of a request.
/// </summary>
public DateTimeOffset Timestamp { get; set; } = new DateTimeOffset(DateTime.UtcNow);
/// <summary>
/// The dictionary of key/value pairs parsed form the callback URI's query string.
/// </summary>
public Dictionary<string, string> Properties { get; set; } = new(StringComparer.Ordinal);
/// <summary>Puts a key/value pair into the dictionary.</summary>
public void Put(string key, string value)
=> Properties[key] = value;
/// <summary>Gets a value for a given key from the dictionary.</summary>
/// <param name="key">Key from the callback URI's query string.</param>
public string Get(string key)
{
if (Properties.TryGetValue(key, out var v))
return v;
return default;
}
/// <summary>The value for the `access_token` key.</summary>
/// <value>Access Token parsed from the callback URI access_token parameter.</value>
public string AccessToken
=> Get("access_token");
/// <summary>The value for the `refresh_token` key.</summary>
/// <value>Refresh Token parsed from the callback URI refresh_token parameter.</value>
public string RefreshToken
=> Get("refresh_token");
/// <summary>The value for the `id_token` key.</summary>
/// <value>The value for the `id_token` key.</value>
/// <remarks>Apple doesn't return an access token on iOS native sign in, but it does return id_token as a JWT.</remarks>
public string IdToken
=> Get("id_token");
/// <summary>
/// The refresh token expiry date as calculated by the timestamp of when the result was created plus
/// the value in seconds for the refresh_token_expires_in key.
/// </summary>
/// <value>Timestamp of the creation of the object instance plus the expires_in seconds parsed from the callback URI.</value>
public DateTimeOffset? RefreshTokenExpiresIn
{
get
{
if (Properties.TryGetValue("refresh_token_expires_in", out var v))
{
if (int.TryParse(v, out var i))
return Timestamp.AddSeconds(i);
}
return null;
}
}
/// <summary>
/// The expiry date as calculated by the timestamp of when the result was created plus
/// the value in seconds for the `expires_in` key.
/// </summary>
/// <value>Timestamp of the creation of the object instance plus the expires_in seconds parsed from the callback URI.</value>
public DateTimeOffset? ExpiresIn
{
get
{
if (Properties.TryGetValue("expires_in", out var v))
{
if (int.TryParse(v, out var i))
return Timestamp.AddSeconds(i);
}
return null;
}
}
}
}