| File: WebAuthenticator\WebAuthenticatorResult.shared.cs | Web Access |
| Project: src\src\Essentials\src\Essentials.csproj (Microsoft.Maui.Essentials) |
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; } } } }