317 lines
9.9 KiB
C#
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
|
|
}
|
|
} |