123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950 |
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.IO;
- using System.Net;
- using System.Security.Authentication;
- using System.Security.Cryptography;
- using System.Text;
- using System.Collections.Specialized;
- using System.Threading;
- using FastReport.Cloud.FastReport;
- using FastReport.Utils;
- using System.Threading.Tasks;
- namespace FastReport.Auth
- {
- /// <summary>
- /// Service for working with auth in the Fast Report.
- /// </summary>
- public class AuthService
- {
- #region Private Fields
- private string code;
- private string code_verifier;
- private string nonce;
- private string scopes;
- private string session;
- private string state;
- private string redirectUri;
- private string lastAuthHost;
- #endregion Private Fields
- #region Public Properties
- /// <summary>
- /// Instance of default Service.
- /// </summary>
- public static AuthService Instance { get; } = new AuthService();
- /// <summary>
- /// Gets or sets indicator to enable or disable personalisation service
- /// </summary>
- public bool IsEnable { get; set; } = true;
- /// <summary>
- /// Setting of the service.
- /// </summary>
- public AppSettings Settings { get; } = new AppSettings();
- /// <summary>
- /// User of the service.
- /// </summary>
- public AppUser User { get; } = new AppUser();
- #endregion Public Properties
- #region Public Methods
- /// <summary>
- /// If FastReport.config contains information about custom server and api-key to it,
- /// this method will reset inner instance with that data. Otherwise default server
- /// will be set.
- /// </summary>
- /// <summary>
- /// The method creates an sign in link.
- /// </summary>
- /// <returns></returns>
- public string GenerateSignInUri(string redirectURI)
- {
- try
- {
- this.nonce = NewRandomString(10);
- this.state = NewRandomString(64);
- this.code_verifier = NewRandomString(128);
- string codeChallenge = Sha256Url(code_verifier);
- StringBuilder sb = new StringBuilder(1024);
- sb.Append(Settings.Host + Settings.AuthorizationEndpoint).Append('?')
- .Append("response_type=").Append(Uri.EscapeDataString(Settings.ResponseType))
- .Append('&')
- .Append("client_id=").Append(Uri.EscapeDataString(Settings.ClientId))
- .Append('&')
- .Append("nonce=").Append(Uri.EscapeDataString(this.nonce))
- .Append('&')
- .Append("redirect_uri=").Append(Uri.EscapeDataString(redirectURI))
- .Append('&')
- .Append("scope=").Append(Uri.EscapeDataString(Settings.Scopes))
- //.Append('&')
- //.Append("response_mode=").Append(Uri.EscapeDataString(Settings.ResponseMode))
- .Append('&')
- .Append("code_challenge_method=").Append(Uri.EscapeDataString(Settings.CodeChallengeMethod))
- .Append('&')
- .Append("code_challenge=").Append(Uri.EscapeDataString(codeChallenge))
- .Append('&')
- .Append("state=").Append(Uri.EscapeDataString(this.state));
- ;
- return sb.ToString();
- }
- catch (Exception e)
- {
- throw new AuthenticationException("Error generating sign in uri, maybe one of the path parameters is null.", e);
- }
- }
- /// <summary>
- /// The method creates an sign out link.
- /// </summary>
- /// <returns></returns>
- public string GenerateSignOutUri(string redirectURI)
- {
- try
- {
- StringBuilder sb = new StringBuilder(1024);
- sb.Append(GetAuthHost() + Settings.EndSessionEndpoint).Append('?')
- .Append("id_token_hint=")
- .Append(Uri.EscapeDataString(User.IdToken))
- .Append("&post_logout_redirect_uri=")
- .Append(Uri.EscapeDataString(redirectURI));
- return sb.ToString();
- }
- catch (Exception e)
- {
- throw new AuthenticationException("Error generating sign out uri, maybe one of the path parameters is null.", e);
- }
- }
- /// <summary>
- /// Returns true, if user has offline_access scope and refresh_token is not null
- /// </summary>
- public bool CanRefresh
- {
- get
- {
- return !String.IsNullOrEmpty(User.RefreshToken) && (User.Scopes == null || User.Scopes != null && Contains(User.Scopes, "offline_access"));
- }
- }
- /// <summary>
- /// If possible, the method updates the user credentials.
- /// </summary>
- /// <returns>True if success</returns>
- public bool Refresh()
- {
- try
- {
- if (CanRefresh)
- {
- var request = HttpWebRequest.Create(new Uri(GetAuthHost() + Settings.TokenEndpoint));
- request.Method = "POST";
- request.ContentType = "application/x-www-form-urlencoded";
- using (Stream requestStream = request.GetRequestStream())
- {
- byte[] bytes = Encoding.UTF8.GetBytes(GenerateTokenRequestBodyByRefresh());
- requestStream.Write(bytes, 0, bytes.Length);
- }
- using (var response = request.GetResponse())
- {
- using (Stream responseStream = response.GetResponseStream())
- {
- using (TextReader tr = new StreamReader(responseStream, Encoding.UTF8))
- {
- var result = tr.ReadToEnd();
- SaveTokens(result);
- ValidateTokens();
- ParseTokens();
- }
- }
- }
- return true;
- }
- }
- catch (Exception ex)
- {
- User.RefreshToken = null;
- }
- return false;
- }
- /// <summary>
- /// The method resets auth, without sign out process.
- /// </summary>
- public void Reset()
- {
- User.Reset();
- }
- /// <summary>
- /// The method shows sign in form and auth the user.
- /// </summary>
- public async Task SignIn(CancellationToken token = default)
- {
- NameValueCollection queryString;
- using (var authServer = new TCPServerListener())
- {
- redirectUri = authServer.RedirectURL;
- redirectUri = redirectUri.Remove(redirectUri.Length - 1);
- var uri = GenerateSignInUri(redirectUri + Settings.RedirectSignInUri);
- authServer.Open();
- ProcessHelper.StartProcess(uri);
- var context = await authServer.WaitConnectAsync(token).ConfigureAwait(false);
- if (context is null)
- {
- return;
- }
- var response = context.Response;
- var request = context.Request;
- response.Redirect(Settings.Host + Settings.RedirectSignInUri);
- response.OutputStream.Close();
- lastAuthHost = Settings.Host;
- queryString = request.QueryString;
- }
- SignInCalback(queryString);
- }
- /// <summary>
- /// The method shows sign out form and resets the user credentials.
- /// </summary>
- public async Task SignOut(CancellationToken token = default)
- {
- using (var authServer = new TCPServerListener())
- {
- redirectUri = authServer.RedirectURL;
- redirectUri = redirectUri.Remove(redirectUri.Length - 1);
- string uri = GenerateSignOutUri(redirectUri + Settings.RedirectSignOutUri);
- authServer.Open();
- ProcessHelper.StartProcess(uri);
- var context = await authServer.WaitConnectAsync(token).ConfigureAwait(false);
- if (context is null)
- {
- return;
- }
- var response = context.Response;
- response.Redirect(GetAuthHost() + Settings.RedirectSignInUri);
- response.OutputStream.Close();
- }
- User.Reset();
- }
- #endregion Public Methods
- #region Internal Methods
- internal static string NewRandomString(int v)
- {
- const string chars = "abcdefghijklmnopqrstuvwxyz1234567890";
- Random r = new Random();
- StringBuilder sb = new StringBuilder(v);
- for (int i = 0; i < v; i++)
- {
- sb.Append(chars[r.Next(chars.Length)]);
- }
- return sb.ToString();
- }
- #endregion Internal Methods
- #region Private Methods
- private string GetAuthHost()
- {
- return string.IsNullOrEmpty(lastAuthHost) ? Settings.Host : lastAuthHost;
- }
- private void SignInCalback(NameValueCollection queryString)
- {
- // Checks for errors.
- if (HasError(queryString))
- return;
- Process(queryString);
- SignInPart2SecondRequest();
- }
- private bool HasError(NameValueCollection query)
- {
- var error = query.Get("error");
- if (error != null)
- {
- if (error == "access_denied")
- return true;
- else
- throw new AuthenticationException(error);
- //output(String.Format("OAuth authorization error: {0}.", error));
- }
- return false;
- }
- private static string Base64UrlToBase64(string base64url)
- {
- string base64 = base64url.Replace('-', '+').Replace('_', '/');
- if (base64.Length % 4 != 0)
- {
- base64 += new string('=', 4 - base64.Length % 4);
- }
- return base64;
- }
- private static string ConvertToString(object v, string defaultValue)
- {
- if (v != null)
- return v.ToString();
- return defaultValue;
- }
- private static string Sha256Url(string input)
- {
- if (String.IsNullOrEmpty(input))
- return string.Empty;
- using (var sha = SHA256.Create())
- {
- var bytes = Encoding.UTF8.GetBytes(input);
- var hash = sha.ComputeHash(bytes);
- return Convert.ToBase64String(hash).Replace('+', '-').Replace('/', '_').Replace("=", "");
- }
- }
- private static bool Contains(IEnumerable<string> scopes, string value)
- {
- foreach (string scope in scopes)
- {
- if (scope == value)
- return true;
- }
- return false;
- }
- private byte[] Download(string url)
- {
- using (MemoryStream memoryStream = new MemoryStream())
- {
- #if MONO
- ServicePointManager.Expect100Continue = true;
- ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
- #endif
- try
- {
- // send second request
- var request = HttpWebRequest.Create(new Uri(url));
- request.Method = "GET";
- using (var response = request.GetResponse())
- {
- using (Stream responseStream = response.GetResponseStream())
- {
- responseStream.CopyTo(memoryStream);
- }
- }
- }
- catch
- {
- }
- return memoryStream.ToArray();
- }
- }
- private string GenerateTokenRequestBodyByCode(string redirectUri)
- {
- try
- {
- StringBuilder sb = new StringBuilder(1024);
- sb
- .Append("grant_type=authorization_code")
- //.Append(Uri.EscapeDataString(Settings.GrandType))
- .Append("&client_id=").Append(Uri.EscapeDataString(Settings.ClientId))
- .Append("&scope=").Append(Uri.EscapeDataString(this.scopes))
- .Append("&redirect_uri=").Append(Uri.EscapeDataString(redirectUri))
- .Append("&code=").Append(Uri.EscapeDataString(this.code))
- .Append("&code_verifier=").Append(Uri.EscapeDataString(this.code_verifier))
- .Append("&client_secret=").Append(Uri.EscapeDataString(Settings.ClientSecret));
- return sb.ToString();
- }
- catch (Exception e)
- {
- throw new AuthenticationException("Error generating token request body, maybe one of the path parameters is null.", e);
- }
- }
- private string GenerateTokenRequestBodyByRefresh()
- {
- try
- {
- StringBuilder sb = new StringBuilder(1024);
- sb
- .Append("grant_type=refresh_token")
- //.Append(Uri.EscapeDataString(Settings.GrandType))
- .Append("&client_id=").Append(Uri.EscapeDataString(Settings.ClientId))
- .Append("&refresh_token=").Append(Uri.EscapeDataString(User.RefreshToken))
- .Append("&client_secret=").Append(Uri.EscapeDataString(Settings.ClientSecret));
- ;
- if (User.Scopes != null && User.Scopes.Length > 0)
- {
- sb.Append("&scope=").Append(Uri.EscapeDataString(String.Join(" ", User.Scopes)));
- }
- return sb.ToString();
- }
- catch (Exception e)
- {
- throw new AuthenticationException("Error generating token request body, maybe one of the path parameters is null.", e);
- }
- }
- private string Gravatar(string email)
- {
- MD5 md5Hasher = MD5.Create();
- byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(email));
- StringBuilder sBuilder = new StringBuilder("https://www.gravatar.com/avatar/");
- for (int i = 0; i < data.Length; i++)
- {
- sBuilder.Append(data[i].ToString("x2"));
- }
- sBuilder.Append("?s=150");
- return sBuilder.ToString();
- }
- /// <summary>
- /// Do not make this method public, use refresh token for save-load. <br/>
- /// You need only refresh token (<see cref="AppUser.RefreshToken"/>) to get a new token set.<br/>
- /// This method is used to save time for starting a designer.
- /// </summary>
- internal void ParseTokens(bool isProgramStart = false)
- {
- try
- {
- if (!String.IsNullOrEmpty(User.IdToken))
- {
- string[] token = User.IdToken.Split('.');
- string payload = token[1];
- JsonBase json
- = JsonBase.FromString(
- Encoding.UTF8.GetString(
- Convert.FromBase64String(
- Base64UrlToBase64(payload)
- )
- )
- );
- User.Subject = ConvertToString(json["sub"], "");
- User.Email = ConvertToString(json["email"], "");
- User.Username = ConvertToString(json["preferred_username"], User.Email);
- User.FullName = ConvertToString(json["name"], "");
- if ((ConvertToString(json["nonce"], nonce) != nonce) && !isProgramStart)
- {
- throw new AuthenticationException("Nonce check error, token is not valid.");
- }
- try
- {
- var url = Gravatar(User.Email);
- var ms = Download(url);
- User.Avatar = ImageHelper.Load(ms);
- }
- catch (Exception e)
- {
- User.Avatar = null;
- }
- }
- }
- catch (AuthenticationException e)
- {
- User.IdToken = "";
- throw e;
- }
- catch (Exception e)
- {
- User.IdToken = "";
- throw new AuthenticationException("Identity token parse error!", e);
- }
- try
- {
- if (!String.IsNullOrEmpty(User.Token))
- {
- string[] token = User.Token.Split('.');
- string payload = token[1];
- JsonBase json
- = JsonBase.FromString(
- Encoding.UTF8.GetString(
- Convert.FromBase64String(
- Base64UrlToBase64(payload)
- )
- )
- );
- double nbf = Convert.ToDouble(json["nbf"]);
- double exp = Convert.ToDouble(json["exp"]);
- double time = exp - nbf;
- User.ExpiresIn = new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(exp).ToLocalTime();
- User.ExpiresInternal = new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(nbf + time * 0.95).ToLocalTime();
- JsonBase scopes = json["scope"] as JsonBase;
- if (scopes != null && scopes.IsArray)
- {
- List<string> allowedScopes = new List<string>();
- for (int i = 0; i < scopes.Count; i++)
- {
- allowedScopes.Add(scopes[i].ToString());
- }
- User.Scopes = allowedScopes.ToArray();
- }
- }
- }
- catch (AuthenticationException e)
- {
- User.Token = "";
- throw e;
- }
- catch (Exception e)
- {
- User.Token = "";
- throw new AuthenticationException("Access token parse error!", e);
- }
- }
- private void Process(NameValueCollection query)
- {
- foreach (var key in query.AllKeys)
- {
- var value = query[key];
- switch (key.ToLower())
- {
- case "code":
- this.code = value;
- break;
- case "scope":
- scopes = value;
- break;
- case "state":
- if (value != this.state)
- throw new Exception("State is not valid");
- break;
- case "session_state":
- this.session = value;
- break;
- }
- }
- }
- private void SaveTokens(string result)
- {
- JsonBase json = JsonBase.FromString(result);
- if (json.ContainsKey("expires_in"))
- {
- var expiresIn = Convert.ToSingle(json["expires_in"]);
- User.ExpiresIn = DateTime.Now.AddSeconds(expiresIn);
- User.ExpiresInternal = DateTime.Now.AddSeconds(expiresIn * 0.95);
- }
- else
- {
- // if no expires_in value, then default token lifetime
- User.ExpiresIn = DateTime.Now.AddMinutes(5);
- User.ExpiresInternal = User.ExpiresIn;
- }
- if (!json.ContainsKey("id_token"))
- {
- throw new AuthenticationException("No id token provided in server response.");
- }
- if (!json.ContainsKey("access_token"))
- {
- throw new AuthenticationException("No access token provided in server response.");
- }
- if (!json.ContainsKey("token_type"))
- {
- throw new AuthenticationException("No token type provided in server response.");
- }
- User.IdToken = json.ReadString("id_token");
- User.Token = json.ReadString("access_token");
- User.TokenType = json.ReadString("token_type");
- User.RefreshToken = json.ReadString("refresh_token");
- }
- private void SignInPart2SecondRequest()
- {
- var request = HttpWebRequest.Create(new Uri(Settings.Host + Settings.TokenEndpoint));
- request.Method = "POST";
- request.ContentType = "application/x-www-form-urlencoded";
- using (Stream requestStream = request.GetRequestStream())
- {
- string requestBody = GenerateTokenRequestBodyByCode(redirectUri + Settings.RedirectSignInUri);
- byte[] bytes = Encoding.UTF8.GetBytes(requestBody);
- requestStream.Write(bytes, 0, bytes.Length);
- }
- using (var response = request.GetResponse())
- {
- using (Stream responseStream = response.GetResponseStream())
- {
- using (TextReader tr = new StreamReader(responseStream, Encoding.UTF8))
- {
- var result = tr.ReadToEnd();
- SaveTokens(result);
- ValidateTokens();
- ParseTokens();
- }
- }
- }
- }
- private void ValidateTokens()
- {
- // External library for validation signature on tokens
- User.IsValid = false;
- }
- #endregion Private Methods
- #region Public Classes
- /// <summary>
- /// Class for store appsettings, by default appsettings is hardcoded.
- /// </summary>
- public class AppSettings
- {
- public AppSettings()
- {
- Host = Res.Get("Forms,AccountWindow,AuthServer");
- }
- private string host;
- #region Public Properties
- /// <summary>
- /// Authorization Endpoint from the OAuth2 specification.
- /// </summary>
- public string AuthorizationEndpoint { get; set; } = "/connect/authorize";
- /// <summary>
- /// Host for callback requests.
- /// </summary>
- public string CallbackHost { get; set; } = "https://id.fast-report.com";
- /// <summary>
- /// Client identifier or client name from the OAuth2 specification.
- /// </summary>
- public string ClientId { get; set; } = "FastReport.Net.Designer";
- /// <summary>
- /// Client secret or client name from the OAuth2 specification.
- /// </summary>
- public string ClientSecret { get; set; } = "91d18a32-1630-66d5-7f43-05d6e2caf02f";
- /// <summary>
- /// Code challenge method from the OAuth2 specification.
- /// </summary>
- public string CodeChallengeMethod { get; set; } = "S256";
- /// <summary>
- /// EndSession Endpoint from the OAuth2 specification.
- /// </summary>
- public string EndSessionEndpoint { get; set; } = "/connect/endsession";
- /// <summary>
- /// Host for sign in requests
- /// </summary>
- public string Host
- {
- get => HttpMessages.Idn.GetAscii(host);
- set => host = value;
- }
- /// <summary>
- /// JSON Web Key Set Endpoint from the OAuth2 specification.
- /// </summary>
- public string JwksEndpoint { get; set; } = "/.well-known/openid-configuration/jwks";
- /// <summary>
- /// Error result
- /// </summary>
- public string RedirectError { get; set; } = "/home/error";
- /// <summary>
- /// Redirent sign in link for this application.
- /// </summary>
- public string RedirectSignInUri { get; set; } = "/native/sign-in";
- /// <summary>
- /// Redirent sign out link for this application.
- /// </summary>
- public string RedirectSignOutUri { get; set; } = "/native/sign-out";
- /// <summary>
- /// Success result
- /// </summary>
- public string RedirectSuccess { get; set; } = "/home/success";
- /// <summary>
- /// Type of the reponse from the OAuth2 specification.
- /// </summary>
- public string ResponseType { get; set; } = "code";
- /// <summary>
- /// Scopes for the request from the OAuth2 specification, splited by space.
- /// </summary>
- public string Scopes { get; set; } = "openid email profile offline_access fr.cloud.role";
- /// <summary>
- /// Token Endpoint from the OAuth2 specification.
- /// </summary>
- public string TokenEndpoint { get; set; } = "/connect/token";
- #endregion Public Properties
- }
- public class AppUser
- {
- #region Private Fields
- private Image avatar;
- private Image defaultAvatar;
- #endregion Private Fields
- #region Public Properties
- /// <summary>
- /// Avatar of the user, by default is 150x150 picture.
- /// </summary>
- public Image Avatar
- {
- get { return avatar; }
- set
- {
- if (avatar != null)
- avatar.Dispose();
- avatar = value;
- }
- }
- /// <summary>
- /// Returns the display avatar of the user, cannot return null
- /// </summary>
- /// <returns></returns>
- public Image DisplayAvatar
- {
- get
- {
- if (avatar != null)
- return avatar;
- if (defaultAvatar == null)
- defaultAvatar = ResourceLoader.GetBitmap("defaultAvatar.jpg");
- return defaultAvatar;
- }
- }
- /// <summary>
- /// Returns the display email of the user, cannot return null
- /// </summary>
- /// <returns></returns>
- public string DisplayEmail
- {
- get
- {
- if (Email == null)
- return "";
- return Email;
- }
- }
- /// <summary>
- /// Returns the display name of the user, cannot return null
- /// </summary>
- /// <returns></returns>
- public string DisplayName
- {
- get
- {
- if (String.IsNullOrEmpty(FullName))
- {
- if (String.IsNullOrEmpty(Username))
- {
- if (String.IsNullOrEmpty(Subject))
- {
- return "";
- }
- return Subject;
- }
- return Username;
- }
- return FullName;
- }
- }
- /// <summary>
- /// Email of the user.
- /// </summary>
- public string Email { get; set; }
- /// <summary>
- /// Local time when the token will go out.
- /// </summary>
- public DateTime ExpiresIn { get; set; }
- /// <summary>
- /// Full name of the user.
- /// </summary>
- public string FullName { get; set; }
- /// <summary>
- /// Returns true if user is authenticated.
- /// </summary>
- public bool IsAuthenticated
- {
- get
- {
- return !String.IsNullOrEmpty(IdToken) && !String.IsNullOrEmpty(Token);
- }
- }
- internal bool IsAuthentificatedAndActive
- {
- get
- {
- return IsAuthenticated && !IsExpired ||
- !string.IsNullOrEmpty(ApiKey);
- }
- }
- /// <summary>
- /// Returns true if token is expired and is need to referesh
- /// </summary>
- public bool IsExpired
- {
- get
- {
- return ExpiresInternal < DateTime.Now;
- }
- }
- /// <summary>
- /// Indicates that token is check by external method, see <see cref="CustomValidator"/> for details.
- /// </summary>
- public bool IsValid { get; set; }
- /// <summary>
- /// List of allowed scopes.
- /// </summary>
- public string[] Scopes { get; set; }
- /// <summary>
- /// Identifier of the user.
- /// </summary>
- public string Subject { get; set; }
- /// <summary>
- /// Type of token for resource request header, e.g. Bearer.
- /// </summary>
- public string TokenType { get; set; }
- /// <summary>
- /// Preferred username of the user.
- /// </summary>
- public string Username { get; set; }
- /// <summary>
- /// User's api key.
- /// </summary>
- public string ApiKey { get; set; }
- #endregion Public Properties
- #region Internal Properties
- /// <summary>
- /// Local time when the token needs to be updated.
- /// </summary>
- internal DateTime ExpiresInternal { get; set; }
- internal string IdToken { get; set; }
- internal string RefreshToken { get; set; }
- internal string Token { get; set; }
- #endregion Internal Properties
- #region Public Methods
- /// <summary>
- /// Reset the values
- /// </summary>
- public void Reset()
- {
- Avatar = null;
- Email = null;
- ExpiresIn = DateTime.MinValue;
- FullName = null;
- IdToken = null;
- IsValid = false;
- RefreshToken = null;
- Scopes = null;
- Subject = null;
- Token = null;
- TokenType = null;
- Username = null;
- }
- #endregion Public Methods
- }
- #endregion Public Classes
- }
- }
|