using System;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using xIdentityHelper;
using xCommons.Attributes;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Models;
using xModels.Dtos;
using static xIdentityHelper.XApiScopeHelper;
namespace xApi.Controllers {
public partial class AccountController {
//
#region Authentication Actions ...
///
/// Retrieve OAuth Discovery Document
///
/// an instance of DiscoveryDocumentResponse
[AllowAnonymous]
[RequireXPowered]
[HttpGet ("DiscoveryDocument")]
public async Task> GetDiscoveryDocument () {
//
try {
//
var result = await identityProvider
.RequestDiscoveryDocument ();
//
// Ceck Response Result ...
if (result.IsError) {
XException.InvalidConfiguration.Throw ();
}
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
///
/// Request AccessToken for Specific XApiScope
///
/// a member of XApiScope
/// an instance of XTokenResponse
[AllowAnonymous]
[RequireXPowered]
[HttpPost ("RequestScopeAccessToken")]
public async Task> RequestScopeAccessToken (
[FromHeader] XApiScope scope
) {
//
// Do Action ...
try {
//
// Validate Args ...
var scopeName = string.Empty;
try {
scopeName = scope.GetStringValue ();
} catch { }
ValidationProvider.NotEmpty (scopeName);
//
var result = await identityProvider
.RequestScopeAccessToken (scopeName);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
///
/// Authenticate User
///
///
/// Sample request:
///
/// {
/// "password": "",
/// "userSelectBy": "",
/// }
///
///
/// User Login Required Info, an instance of XLoginRequest
/// an instance of XTokenResponse
[AllowAnonymous]
[RequireXPowered]
[HttpPost ("Authenticate")]
public async Task> Authenticate (
[FromBody] XLoginRequest model
) {
try {
//
// Validate Args ...
if (!ModelState.IsValid) {
XException.InvalidArgs.Throw ();
}
await ValidationProvider
.GroupValidationBuilder ()
.AddNotNull (model)
.AddNotEmpty (
model.UserSelectBy,
model.Password
)
.ValidateGroupAsync ();
//
var result = await identityProvider
.Authenticate (model);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
///
/// Authenticate User
///
///
/// Sample request:
///
/// {
/// "language": "fa-IR"
/// "password": "",
/// "userSelectBy": "",
/// "device": {
/// "os":"Mac",
/// "browser":"Chrome",
/// "osVersion":"mac-os-x-15",
/// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
/// "deviceType":3,
/// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
/// "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
/// }
/// }
///
///
/// User Login Required Info, an instance of XLoginRequest
/// an instance of XLoginResponse
[AllowAnonymous]
[RequireXPowered]
[HttpPost ("Login")]
public async Task> Login (
[FromBody] XLoginRequest model
) {
try {
//
// Validate Args ...
if (!ModelState.IsValid) {
XException.InvalidArgs.Throw ();
}
await ValidationProvider
.GroupValidationBuilder ()
.AddNotNull (
model,
model.Device)
.AddNotEmpty (
model.Language,
model.UserSelectBy,
model.Password
)
.ValidateGroupAsync ();
//
var result = await identityProvider
.Login (model);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
///
/// Logout User
///
[RequireXPowered]
[HttpPost ("Logout")]
[Authorize (Policy = XPolicies.User)]
public async Task Logout () {
try {
//
var tokens = await RetrieveTokensAsXTokenResponse ();
await identityProvider
.Logout (tokens);
//
return Ok ();
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
///
/// Refresh Expired Tokens
///
///
/// in addition to AccessToken, you had to pass RefreshToken due to Headers
///
/// an instance of XTokenResponse
[AllowAnonymous]
[RequireXPowered]
[HttpPost ("RefreshTokens")]
public async Task> RefreshTokens () {
//
try {
//
// Retrieve Toke Response ...
var model = await RetrieveTokensAsXTokenResponse ();
//
// Validate Args ...
ValidationProvider
.GroupValidationBuilder ()
.AddNotNull (model)
.AddNotEmpty (
model.AccessToken,
model.RefreshToken)
.ValidateGroup ();
//
var result = await identityProvider
.RefreshTokens (model);
//
return Ok (result
.ToDynamicObject ());
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
///
/// Validate a Revision Checksum
///
///
///
[HttpPost ("Validate")]
[Authorize (Policy = XPolicies.EnabledUser)]
public async Task> Validate (
[FromBody] XValidateRevisionRequest model
) {
//
// Do Action ...
try {
//
// Validate Args ...
await ValidationProvider
.GroupValidationBuilder ()
.AddNotNull (model)
.AddNotEmpty (model.Revision)
.ValidateGroupAsync ();
//
// Get Request ...
var tokens = await RetrieveTokensAsXTokenResponse ();
var result = tokens.ValidateRevisionChecksum (
model.Revision,
identityProvider.RevisionSecretKey
);
//
// Return Result
return Ok (result);
} catch (Exception ex) {
//
var result = GetExceptionActionResult (ex);
return result;
}
}
#endregion
//
#region Password Actions ...
///
/// Change a User's Password ...
///
///
/// for this action you have to provide:
/// - Lang: client device currently used locale, such as: en-US.
/// - Password: user's current active password.
/// - NewPassword: user's new password to change.
/// - Device: user's client device which is an instance of XDevice.
/// - ReturnUrl: client application Login URL.
///
/// Sample request:
///
/// {
/// "lang": "fa-IR",
/// "password": ""
/// "newPassword": "",
/// "returnUrl": "http://localhost/login",
/// "device": {
/// "os":"Mac",
/// "browser":"Chrome",
/// "osVersion":"mac-os-x-15",
/// "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
/// "deviceType":3,
/// "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
/// "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
/// }
/// }
///
///
/// an instance of XActionRequest class which provider requirement for action
///
[RequireXPowered]
[HttpPost ("ChangePassword")]
[Authorize (Policy = XPolicies.User)]
[Authorize (Policy = XPolicies.EnabledUser)]
public async Task ChangePassword (
[FromBody] XActionRequest model
) {
//
// Do Action ...
try {
//
// Validate Args ...
if (!ModelState.IsValid) {
XException.InvalidArgs.Throw ();
}
await ValidationProvider
.GroupValidationBuilder ()
.AddNotNull (
model,
model.Device
)
.AddNotEmpty (
model.Lang,
model.Password,
model.NewPassword,
model.ReturnUrl
)
.ValidateGroupAsync ();
//
// Get User Select By ...
var userSelectByParam = GetUserSelectByParam (
model,
forceNotNull : false
);
if (userSelectByParam.IsNullOrEmpty ()) {
userSelectByParam = User.Identity.Name;
}
ValidationProvider.NotEmpty (userSelectByParam);
//
// Get Request ...
var tokens = await RetrieveTokensAsXTokenResponse ();
await identityProvider
.ChangePassword (tokens, model);
//
return Ok ();
} catch (Exception ex) {
//
var exResult = GetExceptionActionResult (ex);
return exResult;
}
}
#endregion
}
}