Files
xIdentityService/Partial/XIdentityProvider+Authentication.cs
T
2024-01-25 04:44:02 +03:30

317 lines
9.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using IdentityModel.Client;
using xCommons.Extensions;
using xExceptions.Constants;
using xHttpService.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityService.Constants;
namespace xIdentityService.Providers {
public partial class XIdentityProvider {
//
#region Authentication Handlers ...
/// <summary>
/// Request for Discovery Document
/// </summary>
/// <returns>an instance of DiscoveryDocumentResponse</returns>
public async Task<DiscoveryDocumentResponse> RequestDiscoveryDocument () {
//
var httpClient = GetHttpClient ();
//
try {
//
var result = httpClient
.GetDiscoveryDocumentAsync (identityConfiguration.Authority)
.ContinueWith (docTask => {
//
httpClient.Dispose ();
return docTask.Result;
});
//
return await result;
} catch {
throw XException.ActionFailed.ToException ();
}
}
/// <summary>
/// Request AccessToken for Specific XApiScope
/// </summary>
/// <param name="scope">a member of <see>XApiScope</see></param>
/// <returns>an instance of <see>XTokenResponse</see></returns>
public async Task<XTokenResponse> RequestScopeAccessToken (string scope) {
//
// Validate Args ...
var scopeName = string.Empty;
try {
scopeName = scope; // scope.GetStringValue ();
} catch { }
if (scopeName.IsNullOrEmpty ()) {
XException.InvalidArgs.Throw ();
}
//
var client = GetRestClient ();
var request = GetRestRequet (
XApiAccountEndpoint.RequestScopeAccessToken,
headers : new Dictionary<string, string> { { XParam.XScope.GetStringValue (), scope.ToString () } });
//
var response = await RunRestRequest<XTokenResponse> (
client,
request,
XHttpMethod.POST
);
//
// Save Token ...
if (!response.IsNull ()) {
await tokenProvider.AddOrUpdateToken (response);
}
//
return response;
}
/// <summary>
/// Validate a token
/// </summary>
/// <param name="model">Authentication Tokens</param>
/// <returns>an instance of TokenIntrospectionResponse</returns>
public async Task<TokenIntrospectionResponse> Introspection (XTokenResponse model) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (model)
.AddNotEmpty (model.AccessToken)
.ValidateGroupAsync ();
//
var httpClient = GetHttpClient ();
//
try {
//
var discoDoc = await RequestDiscoveryDocument ();
if (discoDoc.IsError) {
XException.ActionFailed.Throw ();
}
//
var response = await httpClient.IntrospectTokenAsync (new TokenIntrospectionRequest {
//
Address = discoDoc.IntrospectionEndpoint,
ClientId = identityConfiguration.ClientId,
ClientSecret = identityConfiguration.ClientSecret,
//
Token = model.AccessToken
});
if (response.IsError) {
throw new Exception (response.Error);
}
//
return response;
} catch {
throw XException.ActionFailed.ToException ();
}
}
/// <summary>
/// Authenticate a User
/// </summary>
/// <param name="model">User Login Required Info, an instance of <see>XLoginRequest</see></param>
/// <returns>an instance of <see>XTokenResponse</see></returns>
public async Task<XTokenResponse> Authenticate (XLoginRequest model) {
//
// Validate Args ...
validationProvider
.GroupValidationBuilder ()
.AddNotNull (model)
.AddNotEmpty (
model.UserSelectBy,
model.Password
)
.ValidateGroup ();
//
var client = GetRestClient ();
var request = GetRestRequet (XApiAccountEndpoint.Authenticate);
request.AddJsonBody (model);
//
var response = await RunRestRequest<XTokenResponse> (
client,
request,
XHttpMethod.POST
);
//
// Save Token ...
if (!response.IsNull ()) {
await tokenProvider.AddOrUpdateToken (response);
}
//
return response;
}
/// <summary>
/// Do Login based on XLoginRequest
/// </summary>
/// <param name="model">User Login Required Info, an instance of <see>XLoginRequest</see></param>
/// <returns>an instance of <see>XTokenResponse</see></returns>
public async Task<XLoginResponse> Login (XLoginRequest model) {
//
// Validate Args ...
validationProvider
.GroupValidationBuilder ()
.AddNotNull (model, model.Device)
.AddNotEmpty (
model.UserSelectBy,
model.Password
)
.ValidateGroup ();
//
var client = GetRestClient ();
var request = GetRestRequet (XApiAccountEndpoint.Login);
request.AddJsonBody (model);
//
var response = await RunRestRequest<XLoginResponse> (
client,
request,
XHttpMethod.POST
);
//
if (!response.IsNull ()) {
//
var tokens = response.ToXTokenResponse ();
await tokenProvider.AddOrUpdateToken (tokens);
}
//
return response;
}
/// <summary>
/// Logout from System
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public async Task Logout (XTokenResponse model) {
//
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (model)
.AddNotEmpty (model.AccessToken)
.ValidateGroupAsync ();
//
var isExists = await tokenProvider
.IsTokenExists (model.AccessToken);
if (isExists) {
await tokenProvider
.RemoveToken (model.AccessToken);
}
}
/// <summary>
/// Refresh Tokens
/// </summary>
/// <param name="model">Authentication Tokens</param>
/// <returns>an instance of <see>XTokenResponse</see></returns>
public async Task<XTokenResponse> RefreshTokens (XTokenResponse model) {
//
// Validate Args ...
validationProvider
.GroupValidationBuilder ()
.AddNotNull (model)
.AddNotEmpty (
model.AccessToken,
model.RefreshToken
)
.ValidateGroup ();
//
var client = GetRestClient (model);
//
var request = GetRestRequet (
XApiAccountEndpoint.RefreshTokens,
headers : model.ToHeaderDictionary ());
request.AddJsonBody (model);
//
var response = await RunRestRequest<XTokenResponse> (
client,
request,
XHttpMethod.POST
);
if (!response.IsNull ()) {
await tokenProvider.UpdateToken (response);
}
//
return response;
}
#endregion
//
#region Password Actions Handlers ...
/// <summary>
/// Change Password
/// </summary>
/// <param name="tokens">Authentication Tokens</param>
/// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
/// <returns></returns>
public async Task ChangePassword (
XTokenResponse tokens,
XActionRequest model
) {
//
// Validate Args ...
await validationProvider
.GroupValidationBuilder ()
.AddNotNull (tokens, model)
.AddNotEmpty (
model.Lang,
model.Password,
model.NewPassword,
model.ReturnUrl)
.AddNotNull (model.Device)
.ValidateGroupAsync ();
//
// Validate User Select By Param ...
var userSelectByParam = GetUserSelectByParam (
model,
forceNotNull : true,
excludes : null);
//
var client = GetRestClient (tokens);
var request = GetRestRequet (
XApiAccountEndpoint.ChangePassword,
headers : tokens.ToHeaderDictionary ());
request.AddJsonBody (model);
//
var response = await RunRestRequest<Object> (
client,
request,
XHttpMethod.POST
);
}
#endregion
}
}