228 lines
14 KiB
C#
228 lines
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
using System.Security.Claims;
|
|
using System.Threading.Tasks;
|
|
using Asp.Versioning;
|
|
using AutoMapper;
|
|
using gehGassi.Core.Interfaces;
|
|
using gehGassi.Domain.Users;
|
|
using gehGassi.Dto;
|
|
using gehGassi.Web.Auth;
|
|
using gehGassi.Web.Helper;
|
|
using Microsoft.AspNetCore.Authentication;
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace gehGassi.Web.Controllers.Api
|
|
{
|
|
[ApiController]
|
|
[ApiVersion(1)]
|
|
[Route("api/mobileauth")]
|
|
[Route("api/v{v:apiVersion}/mobileauth")]
|
|
public class ApiMobileAuthController : ApiBaseController
|
|
{
|
|
private readonly ITokenService _tokenService;
|
|
private readonly UserManager<ApplicationUser> _userManager;
|
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
private readonly IRefreshTokenService _refreshTokenService;
|
|
const string callbackScheme = "gehgassiapp";
|
|
|
|
public ApiMobileAuthController(IMapper mapper, IOptions<LocalizationOptions> localizationOptions, IAppUserService appUserService,
|
|
ITokenService tokenService, UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager, IRefreshTokenService refreshTokenService) : base(mapper, localizationOptions, appUserService)
|
|
{
|
|
_tokenService = tokenService;
|
|
_userManager = userManager;
|
|
_signInManager = signInManager;
|
|
_refreshTokenService = refreshTokenService;
|
|
}
|
|
|
|
[HttpGet("{scheme}")]
|
|
public async Task Get([FromRoute] string scheme)
|
|
{
|
|
try
|
|
{
|
|
var errorCode = CommunicationErrors.Undefined;
|
|
|
|
var auth = await Request.HttpContext.AuthenticateAsync(scheme);
|
|
|
|
if (!auth.Succeeded || auth?.Principal == null || !auth.Principal.Identities.Any(id => id.IsAuthenticated) || string.IsNullOrEmpty(auth.Properties.GetTokenValue("access_token")))
|
|
{
|
|
// Not authenticated, challenge
|
|
await Request.HttpContext.ChallengeAsync(scheme);
|
|
}
|
|
else
|
|
{
|
|
var email = string.Empty;
|
|
var providerKey = string.Empty;
|
|
var givenName = string.Empty;
|
|
var surname = string.Empty;
|
|
var token = string.Empty;
|
|
|
|
if (auth.Principal != null && auth.Principal.Identities != null && auth.Principal.Identities.Any())
|
|
{
|
|
var claims = auth.Principal.Identities.FirstOrDefault()?.Claims;
|
|
if (claims != null)
|
|
{
|
|
var claimsList = claims.ToList();
|
|
if (claimsList.Any())
|
|
{
|
|
email = claimsList?.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value;
|
|
providerKey = claimsList?.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
|
|
givenName = claimsList?.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value;
|
|
surname = claimsList?.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value;
|
|
|
|
if (!string.IsNullOrWhiteSpace(email) && !string.IsNullOrWhiteSpace(providerKey))
|
|
{
|
|
//Umgestellt auf Providerkey, falls der Benutzer die Email-Adresse geändert hat, wenn kein externer Login vorhanden, dann mit email
|
|
var user = await _userManager.FindByLoginAsync("Google", providerKey) ?? await _userManager.FindByEmailAsync(email);
|
|
if (user != null)
|
|
{
|
|
if (await _userManager.IsLockedOutAsync(user) == false)
|
|
{
|
|
if (await _userManager.IsEmailConfirmedAsync(user))
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(user.AppUserId))
|
|
{
|
|
var appUser = await AppUserService.GetAsync(user.AppUserId);
|
|
if (appUser != null)
|
|
{
|
|
if (appUser.Locked && appUser.LockedUntil < DateTimeOffset.UtcNow)
|
|
{
|
|
appUser.Locked = false;
|
|
appUser.LockedUntil = null;
|
|
await AppUserService.CommitAsync("System");
|
|
}
|
|
|
|
if (!appUser.Locked)
|
|
{
|
|
var usersClaims = new List<Claim>()
|
|
{
|
|
new Claim(ClaimTypes.Name, user.UserName),
|
|
new Claim(ClaimTypes.GivenName, user.FirstName),
|
|
new Claim(ClaimTypes.Surname, user.LastName),
|
|
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
|
new Claim(ClaimTypes.UserData, user.Photo ?? ""),
|
|
new Claim(ClaimConstants.AppUserIdClaimType, user.AppUserId ?? ""),
|
|
};
|
|
|
|
var roles = await _userManager.GetRolesAsync(user);
|
|
foreach (var role in roles)
|
|
{
|
|
usersClaims.Add(new Claim(ClaimTypes.Role, role));
|
|
}
|
|
|
|
token = _tokenService.GenerateAccessToken(usersClaims);
|
|
await _refreshTokenService.RemoveExpiredAsync(user.Id, user.UserName);
|
|
|
|
user.LastLoginDate = DateTimeOffset.UtcNow;
|
|
await _userManager.UpdateAsync(user);
|
|
|
|
var externalLogins = await _userManager.GetLoginsAsync(user);
|
|
if (externalLogins?.FirstOrDefault(c => c.LoginProvider == "Google") == null)
|
|
{
|
|
await _userManager.AddLoginAsync(user, new UserLoginInfo("Google", providerKey, user.FullName));
|
|
}
|
|
|
|
errorCode = CommunicationErrors.None;
|
|
|
|
var responseValues = new Dictionary<string, string>
|
|
{
|
|
{ "error_code", errorCode.ToString() },
|
|
{ "access_token", token },
|
|
{ "email", email },
|
|
{ "register", false.ToString() },
|
|
{ "givenname", givenName },
|
|
{ "surname", surname },
|
|
{ "providerkey", providerKey }
|
|
};
|
|
var callBackUrl = callbackScheme + "://#" + string.Join(
|
|
"&",
|
|
responseValues.Where(kvp => !string.IsNullOrEmpty(kvp.Value) && kvp.Value != "-1")
|
|
.Select(kvp => $"{WebUtility.UrlEncode(kvp.Key)}={WebUtility.UrlEncode(kvp.Value)}"));
|
|
Request.HttpContext.Response.Redirect(callBackUrl);
|
|
return;
|
|
}
|
|
else
|
|
errorCode = CommunicationErrors.Login_LockedOut;
|
|
}
|
|
else
|
|
errorCode = CommunicationErrors.Login_Assignment_Missing;
|
|
}
|
|
else
|
|
errorCode = CommunicationErrors.Login_Assignment_Missing;
|
|
}
|
|
else
|
|
errorCode = CommunicationErrors.Login_Email_NotConfirmed;
|
|
}
|
|
else
|
|
errorCode = CommunicationErrors.Login_LockedOut;
|
|
}
|
|
else
|
|
{
|
|
//Es gibt den Benutzer nicht. Registrierungs-Variante
|
|
|
|
token = auth.Properties.GetTokenValue("access_token");
|
|
if (!string.IsNullOrEmpty(token))
|
|
{
|
|
errorCode = CommunicationErrors.None;
|
|
|
|
var responseValues = new Dictionary<string, string>
|
|
{
|
|
{ "error_code", errorCode.ToString() },
|
|
{ "access_token", token },
|
|
{ "email", email },
|
|
{ "register", true.ToString() },
|
|
{ "givenname", givenName },
|
|
{ "surname", surname },
|
|
{ "providerkey", providerKey }
|
|
};
|
|
var callBackUrl = callbackScheme + "://#" + string.Join(
|
|
"&",
|
|
responseValues.Where(kvp => !string.IsNullOrEmpty(kvp.Value) && kvp.Value != "-1")
|
|
.Select(kvp => $"{WebUtility.UrlEncode(kvp.Key)}={WebUtility.UrlEncode(kvp.Value)}"));
|
|
Request.HttpContext.Response.Redirect(callBackUrl);
|
|
return;
|
|
}
|
|
else
|
|
errorCode = CommunicationErrors.Undefined;
|
|
}
|
|
}
|
|
if(errorCode == CommunicationErrors.None)
|
|
errorCode = CommunicationErrors.Register_Email_Exists;
|
|
}
|
|
if (errorCode == CommunicationErrors.None)
|
|
errorCode = CommunicationErrors.Common_Model_Invalid;
|
|
}
|
|
if (errorCode == CommunicationErrors.None)
|
|
errorCode = CommunicationErrors.Common_Exists;
|
|
}
|
|
var errorResponseValues = new Dictionary<string, string>
|
|
{
|
|
{ "error_code", errorCode.ToString() },
|
|
{ "access_token", token },
|
|
{ "email", email },
|
|
{ "register", false.ToString() },
|
|
{ "givenname", givenName },
|
|
{ "surname", surname },
|
|
{ "providerkey", providerKey }
|
|
};
|
|
var errorCallBackUrl = callbackScheme + "://#" + string.Join(
|
|
"&",
|
|
errorResponseValues.Where(kvp => !string.IsNullOrEmpty(kvp.Value) && kvp.Value != "-1")
|
|
.Select(kvp => $"{WebUtility.UrlEncode(kvp.Key)}={WebUtility.UrlEncode(kvp.Value)}"));
|
|
Request.HttpContext.Response.Redirect(errorCallBackUrl);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Request.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
|
|
}
|
|
}
|
|
}
|
|
}
|