Initial ...

This commit is contained in:
2026-03-22 14:08:25 +03:30
commit d3464ef39c
71 changed files with 19087 additions and 0 deletions
@@ -0,0 +1,342 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xExceptions.Constants;
using xExceptions.Models;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIds.Extensions;
using static IdentityModel.OidcConstants;
namespace xIds.Providers
{
public partial class XIdentityManager
{
//
#region Identity Actions ...
/// <summary>
/// Request for Discovery Document
/// </summary>
/// <returns>an instance of <see>DiscoveryDocumentResponse</see></returns>
public async Task<DiscoveryDocumentResponse> RequestDiscoveryDocument()
{
//
var httpClient = GetHttpClient();
var result = httpClient
.GetDiscoveryDocumentAsync(IdentityResourceConfiguration.Authority)
.ContinueWith(docTask =>
{
//
httpClient.Dispose();
return docTask.Result;
});
//
return await result;
}
/// <summary>
/// Request AccessToken for Specific XApiScope
/// </summary>
/// <param name="scope">a member of <see>XApiScope</see></param>
/// <returns>an instance of <see>TokenResponse</see></returns>
public async Task<IdentityModel.Client.TokenResponse> RequestScopeAccessToken(
string scope
)
{
//
// Validate Args ...
if (scope.IsNullOrEmpty())
{
XException.InvalidArgs.Throw();
}
//
// Retrieve Disco Doc ...
var discoDoc = await RequestDiscoveryDocument();
if (discoDoc.IsError)
{
XException.ActionFailed.Throw();
}
//
var request = new ClientCredentialsTokenRequest
{
Address = discoDoc.TokenEndpoint,
GrantType = GrantTypes.ClientCredentials,
ClientId = IdentityResourceConfiguration.ClientId,
ClientSecret = IdentityResourceConfiguration.ClientSecret,
Scope = scope
};
//
var httpClient = GetHttpClient();
var result = await httpClient
.RequestClientCredentialsTokenAsync(request)
.ContinueWith(response =>
{
//
httpClient.Dispose();
return response.Result;
});
//
return result;
}
/// <summary>
/// Authenticate a User
/// </summary>
/// <param name="model">an instance of <see>XLoginRequest</see> class which represent Authentication requirements</param>
/// <returns>an instance of <see>TokenResponse</see></returns>
public async Task<IdentityModel.Client.TokenResponse> Authenticate(
XLoginRequest model
)
{
//
// Validate Args ...
ValidationProvider
.GroupValidationBuilder()
.AddNotNull(model)
.AddNotEmpty(
model.UserSelectBy,
model.Password
)
.ValidateGroup();
//
// Retrieve Disco Doc ...
var discoDoc = await RequestDiscoveryDocument();
if (discoDoc.IsError)
{
XException.ActionFailed.Throw();
}
//
// Create Request ...
var request = new PasswordTokenRequest
{
//
Address = discoDoc.TokenEndpoint,
//
GrantType = GrantTypes.ClientCredentials,
ClientId = IdentityResourceConfiguration.ClientId,
ClientSecret = IdentityResourceConfiguration.ClientSecret,
//
UserName = model.UserSelectBy,
Password = model.Password,
//
// Pass Device to Request ...
Parameters = { { "force", false.ToJSON () }
}
};
//
var httpClient = GetHttpClient();
var result = await httpClient
.RequestPasswordTokenAsync(request)
.ContinueWith(response =>
{
//
httpClient.Dispose();
return response.Result;
});
//
return result;
}
/// <summary>
/// Do Login based on XLoginRequest
/// </summary>
/// <param name="model">an instance of <see>XLoginRequest</see> class which represent Authentication requirements</param>
/// <returns>an instance of <see>XLoginResponse</see></returns>
public async Task<XLoginResponse> Login(
XLoginRequest model
)
{
//
// Validate Args ...
ValidationProvider
.GroupValidationBuilder()
.AddNotNull(model, model.Device)
.AddNotEmpty(
model.UserSelectBy,
model.Password
)
.ValidateGroup();
//
// Get Token Response ...
//
// Retrieve Disco Doc ...
var discoDoc = await RequestDiscoveryDocument();
Logger.LogInformation($"discoDoc: {discoDoc.ToJSON()}");
if (discoDoc.IsError)
{
XException.ActionFailed.Throw();
}
//
// Create Request ...
var request = new PasswordTokenRequest
{
//
Address = discoDoc.TokenEndpoint,
//
GrantType = GrantTypes.ClientCredentials,
ClientId = IdentityResourceConfiguration.ClientId,
ClientSecret = IdentityResourceConfiguration.ClientSecret,
//
UserName = model.UserSelectBy,
Password = model.Password,
//
// Pass Device to Request ...
Parameters = { { "force", false.ToJSON () },
{ "device", model.Device.ToJSON () },
{ "language", model.Language }
}
};
//
var httpClient = GetHttpClient();
var authResponse = await httpClient
.RequestPasswordTokenAsync(request)
.ContinueWith(response =>
{
//
httpClient.Dispose();
return response.Result;
});
//
// Check If Response Has Error ...
Logger.LogInformation($"AuthResponse: {authResponse.ToJSON()}");
//
if (authResponse.IsError)
{
throw authResponse.GetException();
}
//
// Create XLoginResponse Model ...
var result = authResponse.CreateXLoginResponse();
//
// Get ans Set User Profile ...
result.Profile = await GetUserProfileAsync(model.UserSelectBy, model.UserSelectBy);
//
return result;
}
/// <summary>
/// Refresh Tokens
/// </summary>
/// <param name="model">Authentication Tokens, instance of <see>XTokenResponse</see></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 authResponse = await RequestDiscoveryDocument()
.ContinueWith((discoTask) =>
{
//
var discoDoc = discoTask.Result;
if (discoDoc.IsError)
{
XException.ActionFailed.Throw();
}
//
using (var httpClient = GetHttpClient())
{
return httpClient.RequestRefreshTokenAsync(new RefreshTokenRequest
{
//
Address = discoDoc.TokenEndpoint,
GrantType = GrantTypes.RefreshToken,
ClientId = IdentityResourceConfiguration.ClientId,
ClientSecret = IdentityResourceConfiguration.ClientSecret,
RefreshToken = model.RefreshToken
}).Result;
}
});
//
// Check If Response Has Error ...
if (authResponse.IsError)
{
//
XError error = authResponse.ErrorDescription.FromJSON<XError>();
throw error.ToException();
}
//
// Create XLoginResponse Model ...
var result = authResponse.CreateXTokenResponse();
//
return result;
}
#endregion
//
#region Requirements ...
/// <summary>
/// Get an Instance of Http Client
/// </summary>
/// <returns>an instance of <see>HttpClient</see></returns>
public HttpClient GetHttpClient()
{
//
HttpClient httpClient = null;
httpClient = new HttpClient();
var httpClientHandler = new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) =>
{
//
Logger.LogInformation(
$"SSL Handler: {Environment.NewLine} sender: {sender}, {Environment.NewLine} cert: {cert}, {Environment.NewLine} chain: {chain}, {Environment.NewLine} sslPolicyErrors: {sslPolicyErrors}"
);
//
return true;
},
ClientCertificateOptions = ClientCertificateOption.Manual,
};
//
httpClient = new HttpClient(httpClientHandler);
//
return httpClient;
}
#endregion
}
}