feat: add authentication using Google OAuth token
https://levelup.gitconnected.com/how-to-sign-in-with-google-in-angular-and-use-jwt-based-net-core-api-authentication-rsa-6635719fb86c
This commit is contained in:
parent
59c3a9f704
commit
ceaba3eb2d
@ -3,7 +3,7 @@ namespace Server.Configurations;
|
||||
public class SmtpCredentials
|
||||
{
|
||||
public string Host { get; set; } = null!;
|
||||
public int Port { get; set; }
|
||||
public string Port { get; set; }
|
||||
public string User { get; set; } = null!;
|
||||
public string Password { get; set; } = null!;
|
||||
}
|
@ -49,7 +49,7 @@ public class AuthenticationController : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost("authenticate")]
|
||||
public async Task<IActionResult> GetTokenAsync(AuthenticationRequest authRequest)
|
||||
public async Task<IActionResult> Authenticate(AuthenticationRequest authRequest)
|
||||
{
|
||||
var (succeeded, authResponse, refreshToken) =
|
||||
await _authService.AuthenticateAsync(authRequest);
|
||||
@ -64,6 +64,22 @@ public class AuthenticationController : ControllerBase
|
||||
return Ok(authResponse);
|
||||
}
|
||||
|
||||
[HttpPost("googleoauth")]
|
||||
public async Task<IActionResult> AuthenticateWithGoogle(GoogleAuthenticationRequest authRequest)
|
||||
{
|
||||
var (succeeded, authResponse, refreshToken) =
|
||||
await _authService.AuthenticateWithGoogleAsync(authRequest);
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
return BadRequest(authResponse);
|
||||
}
|
||||
|
||||
SetRefreshTokenInCookie(refreshToken!);
|
||||
|
||||
return Ok(authResponse);
|
||||
}
|
||||
|
||||
[HttpPost("renew-session")]
|
||||
public async Task<IActionResult> RenewTokens()
|
||||
{
|
||||
|
@ -16,20 +16,22 @@ using Server.Services;
|
||||
using SharedModels.DataTransferObjects;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
var services = builder.Services;
|
||||
var configuration = builder.Configuration;
|
||||
|
||||
// Add services to the container.
|
||||
|
||||
builder.Services.AddControllers().AddNewtonsoftJson(options => {
|
||||
services.AddControllers().AddNewtonsoftJson(options => {
|
||||
options.SerializerSettings.Formatting = Formatting.Indented;
|
||||
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
|
||||
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Error;
|
||||
options.SerializerSettings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
|
||||
});
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
services.AddHttpContextAccessor();
|
||||
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen(options => {
|
||||
services.AddEndpointsApiExplorer();
|
||||
services.AddSwaggerGen(options => {
|
||||
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
|
||||
Scheme = "Bearer",
|
||||
BearerFormat = "JWT",
|
||||
@ -53,22 +55,25 @@ builder.Services.AddSwaggerGen(options => {
|
||||
});
|
||||
});
|
||||
|
||||
builder.Services.AddCors(options => {
|
||||
services.AddCors(options => {
|
||||
options.AddDefaultPolicy(policy => policy.AllowAnyOrigin()
|
||||
.AllowAnyHeader().AllowAnyMethod());
|
||||
});
|
||||
|
||||
builder.Services.AddIdentityCore<User>(options =>
|
||||
services.AddIdentityCore<User>(options =>
|
||||
{
|
||||
options.User.RequireUniqueEmail = true;
|
||||
options.Password.RequiredLength = 8;
|
||||
}).AddRoles<IdentityRole>().AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();
|
||||
|
||||
// Configuration from AppSettings
|
||||
builder.Services.Configure<Jwt>(builder.Configuration.GetSection("Jwt"));
|
||||
services.Configure<SmtpCredentials>(configuration.GetSection("SmtpCredentials"));
|
||||
services.Configure<Jwt>(configuration.GetSection("Jwt"));
|
||||
|
||||
// Adding Authentication - JWT
|
||||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddJwtBearer(options => {
|
||||
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddJwtBearer(options =>
|
||||
{
|
||||
// options.RequireHttpsMetadata = false;
|
||||
// options.SaveToken = false;
|
||||
options.TokenValidationParameters = new TokenValidationParameters
|
||||
@ -77,15 +82,14 @@ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
ValidateAudience = false,
|
||||
ValidateIssuer = false,
|
||||
ValidateLifetime = true,
|
||||
ValidIssuer = builder.Configuration["Jwt:Issuer"],
|
||||
ValidAudience = builder.Configuration["Jwt:Audience"],
|
||||
ValidIssuer = configuration["Jwt:Issuer"],
|
||||
ValidAudience = configuration["Jwt:Audience"],
|
||||
IssuerSigningKey = new SymmetricSecurityKey(
|
||||
Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
|
||||
Encoding.UTF8.GetBytes(configuration["Jwt:Key"]))
|
||||
};
|
||||
});
|
||||
builder.Services.Configure<SmtpCredentials>(builder.Configuration.GetSection("SmtpCredentials"));
|
||||
|
||||
builder.Services.AddAuthorization(options => {
|
||||
services.AddAuthorization(options => {
|
||||
// options.FallbackPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
|
||||
|
||||
// Policies for accessing endpoints on a top level based on user role
|
||||
@ -100,62 +104,62 @@ builder.Services.AddAuthorization(options => {
|
||||
policy.RequireRole(Identity.Roles.Administrator.ToString()));
|
||||
});
|
||||
|
||||
builder.Services.AddAutoMapper(typeof(MapperInitializer));
|
||||
services.AddAutoMapper(typeof(MapperInitializer));
|
||||
|
||||
builder.Services.AddScoped<IEmailSenderService, EmailSenderService>();
|
||||
builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
|
||||
services.AddScoped<IEmailSenderService, EmailSenderService>();
|
||||
services.AddScoped<IAuthenticationService, AuthenticationService>();
|
||||
|
||||
builder.Services.AddScoped<ICountryManagementService, CountryManagementService>();
|
||||
builder.Services.AddScoped<IStateManagementService, StateManagementService>();
|
||||
builder.Services.AddScoped<ICityManagementService, CityManagementService>();
|
||||
builder.Services.AddScoped<IAddressManagementService, AddressManagementService>();
|
||||
builder.Services.AddScoped<ITicketManagementService, TicketManagementService>();
|
||||
builder.Services.AddScoped<ITicketGroupManagementService, TicketGroupManagementService>();
|
||||
builder.Services.AddScoped<IReviewManagementService, ReviewManagementService>();
|
||||
builder.Services.AddScoped<ICompanyManagementService, CompanyManagementService>();
|
||||
builder.Services.AddScoped<IVehicleManagementService, VehicleManagementService>();
|
||||
builder.Services.AddScoped<IVehicleEnrollmentManagementService, VehicleEnrollmentManagementService>();
|
||||
builder.Services.AddScoped<IRouteManagementService, RouteManagementService>();
|
||||
builder.Services.AddScoped<IRouteAddressManagementService, RouteAddressManagementService>();
|
||||
services.AddScoped<ICountryManagementService, CountryManagementService>();
|
||||
services.AddScoped<IStateManagementService, StateManagementService>();
|
||||
services.AddScoped<ICityManagementService, CityManagementService>();
|
||||
services.AddScoped<IAddressManagementService, AddressManagementService>();
|
||||
services.AddScoped<ITicketManagementService, TicketManagementService>();
|
||||
services.AddScoped<ITicketGroupManagementService, TicketGroupManagementService>();
|
||||
services.AddScoped<IReviewManagementService, ReviewManagementService>();
|
||||
services.AddScoped<ICompanyManagementService, CompanyManagementService>();
|
||||
services.AddScoped<IVehicleManagementService, VehicleManagementService>();
|
||||
services.AddScoped<IVehicleEnrollmentManagementService, VehicleEnrollmentManagementService>();
|
||||
services.AddScoped<IRouteManagementService, RouteManagementService>();
|
||||
services.AddScoped<IRouteAddressManagementService, RouteAddressManagementService>();
|
||||
|
||||
builder.Services.AddScoped<ISortHelper<ExpandoObject>, SortHelper<ExpandoObject>>();
|
||||
services.AddScoped<ISortHelper<ExpandoObject>, SortHelper<ExpandoObject>>();
|
||||
|
||||
builder.Services.AddScoped<IDataShaper<CountryDto>, DataShaper<CountryDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<StateDto>, DataShaper<StateDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<CityDto>, DataShaper<CityDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<AddressDto>, DataShaper<AddressDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<TicketDto>, DataShaper<TicketDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<TicketGroupDto>, DataShaper<TicketGroupDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<TicketGroupWithTicketsDto>, DataShaper<TicketGroupWithTicketsDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<ReviewDto>, DataShaper<ReviewDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<CompanyDto>, DataShaper<CompanyDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<VehicleDto>, DataShaper<VehicleDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<VehicleEnrollmentDto>, DataShaper<VehicleEnrollmentDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<VehicleEnrollmentWithDetailsDto>, DataShaper<VehicleEnrollmentWithDetailsDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<RouteDto>, DataShaper<RouteDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<RouteWithAddressesDto>, DataShaper<RouteWithAddressesDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<RouteAddressDto>, DataShaper<RouteAddressDto>>();
|
||||
services.AddScoped<IDataShaper<CountryDto>, DataShaper<CountryDto>>();
|
||||
services.AddScoped<IDataShaper<StateDto>, DataShaper<StateDto>>();
|
||||
services.AddScoped<IDataShaper<CityDto>, DataShaper<CityDto>>();
|
||||
services.AddScoped<IDataShaper<AddressDto>, DataShaper<AddressDto>>();
|
||||
services.AddScoped<IDataShaper<TicketDto>, DataShaper<TicketDto>>();
|
||||
services.AddScoped<IDataShaper<TicketGroupDto>, DataShaper<TicketGroupDto>>();
|
||||
services.AddScoped<IDataShaper<TicketGroupWithTicketsDto>, DataShaper<TicketGroupWithTicketsDto>>();
|
||||
services.AddScoped<IDataShaper<ReviewDto>, DataShaper<ReviewDto>>();
|
||||
services.AddScoped<IDataShaper<CompanyDto>, DataShaper<CompanyDto>>();
|
||||
services.AddScoped<IDataShaper<VehicleDto>, DataShaper<VehicleDto>>();
|
||||
services.AddScoped<IDataShaper<VehicleEnrollmentDto>, DataShaper<VehicleEnrollmentDto>>();
|
||||
services.AddScoped<IDataShaper<VehicleEnrollmentWithDetailsDto>, DataShaper<VehicleEnrollmentWithDetailsDto>>();
|
||||
services.AddScoped<IDataShaper<RouteDto>, DataShaper<RouteDto>>();
|
||||
services.AddScoped<IDataShaper<RouteWithAddressesDto>, DataShaper<RouteWithAddressesDto>>();
|
||||
services.AddScoped<IDataShaper<RouteAddressDto>, DataShaper<RouteAddressDto>>();
|
||||
|
||||
builder.Services.AddScoped<IPager<ExpandoObject>, Pager<ExpandoObject>>();
|
||||
services.AddScoped<IPager<ExpandoObject>, Pager<ExpandoObject>>();
|
||||
|
||||
builder.Services.AddScoped<AutomationService>();
|
||||
builder.Services.AddScoped<IReportService, ReportService>();
|
||||
services.AddScoped<AutomationService>();
|
||||
services.AddScoped<IReportService, ReportService>();
|
||||
|
||||
builder.Services.AddScoped<IStatisticsService, StatisticsService>();
|
||||
builder.Services.AddScoped<IDataShaper<UserDto>, DataShaper<UserDto>>();
|
||||
builder.Services.AddScoped<IDataShaper<ExpandoObject>, DataShaper<ExpandoObject>>();
|
||||
services.AddScoped<IStatisticsService, StatisticsService>();
|
||||
services.AddScoped<IDataShaper<UserDto>, DataShaper<UserDto>>();
|
||||
services.AddScoped<IDataShaper<ExpandoObject>, DataShaper<ExpandoObject>>();
|
||||
|
||||
// Adding DB Context with PostgreSQL
|
||||
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
|
||||
builder.Services.AddDbContext<ApplicationDbContext>(options =>
|
||||
var connectionString = configuration.GetConnectionString("DefaultConnection");
|
||||
services.AddDbContext<ApplicationDbContext>(options =>
|
||||
options.UseNpgsql(connectionString));
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Data seeding
|
||||
using var scope = app.Services.CreateScope();
|
||||
var services = scope.ServiceProvider;
|
||||
await SeedData.Initialize(services);
|
||||
var serviceProvider = scope.ServiceProvider;
|
||||
await SeedData.Initialize(serviceProvider);
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
|
@ -8,7 +8,9 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0" />
|
||||
<PackageReference Include="Google.Apis.Auth" Version="1.60.0" />
|
||||
<PackageReference Include="MailKit" Version="4.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="6.0.9" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.9" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.9" />
|
||||
|
@ -3,6 +3,7 @@ using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Google.Apis.Auth;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
@ -17,24 +18,28 @@ namespace Server.Services;
|
||||
|
||||
public class AuthenticationService : IAuthenticationService
|
||||
{
|
||||
private readonly Jwt _jwt;
|
||||
|
||||
private readonly UserManager<User> _userManager;
|
||||
private readonly RoleManager<IdentityRole> _roleManager;
|
||||
private readonly Jwt _jwt;
|
||||
private readonly IHttpContextAccessor _contextAccessor;
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
private readonly IEmailSenderService _emailSender;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public AuthenticationService(UserManager<User> userManager,
|
||||
RoleManager<IdentityRole> roleManager, IOptions<Jwt> jwt,
|
||||
IHttpContextAccessor contextAccessor, LinkGenerator linkGenerator,
|
||||
IEmailSenderService emailSender)
|
||||
IEmailSenderService emailSender, IConfiguration configuration)
|
||||
{
|
||||
_jwt = jwt.Value;
|
||||
|
||||
_userManager = userManager;
|
||||
_roleManager = roleManager;
|
||||
_jwt = jwt.Value;
|
||||
_contextAccessor = contextAccessor;
|
||||
_linkGenerator = linkGenerator;
|
||||
_emailSender = emailSender;
|
||||
_configuration = configuration;
|
||||
|
||||
_userManager.UserValidators.Clear();
|
||||
}
|
||||
@ -70,15 +75,23 @@ public class AuthenticationService : IAuthenticationService
|
||||
return (false, $"{createUserResult.Errors?.First().Description}");
|
||||
}
|
||||
|
||||
await _userManager.AddToRoleAsync(user, Constants.Identity.DefaultRole.ToString());
|
||||
|
||||
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||
var confirmationLink = _linkGenerator.GetUriByAction(_contextAccessor.HttpContext,
|
||||
"confirmEmail", "authentication",
|
||||
new { email = user.Email, token = token, redirectionUrl = regRequest.EmailConfirmationRedirectUrl },
|
||||
_contextAccessor.HttpContext.Request.Scheme);
|
||||
|
||||
await _emailSender.SendMail(user.Email, "Email confirmation", confirmationLink);
|
||||
try
|
||||
{
|
||||
await _emailSender.SendMail(user.Email, "Email confirmation", confirmationLink);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
await _userManager.AddToRoleAsync(user, Constants.Identity.DefaultRole.ToString());
|
||||
return (true, $"User registered with email {user.Email}. Before signing in confirm your email" +
|
||||
$"by following a link sent to registered email address.");
|
||||
}
|
||||
@ -100,8 +113,8 @@ public class AuthenticationService : IAuthenticationService
|
||||
return (true, $"Email {email} confirmed");
|
||||
}
|
||||
|
||||
public async Task<(bool succeeded, AuthenticationResponse authResponse,
|
||||
string? refreshToken)> AuthenticateAsync(AuthenticationRequest authRequest)
|
||||
public async Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
||||
AuthenticateAsync(AuthenticationRequest authRequest)
|
||||
{
|
||||
var authResponse = new AuthenticationResponse();
|
||||
|
||||
@ -145,6 +158,56 @@ public class AuthenticationService : IAuthenticationService
|
||||
return (true, authResponse, refreshTokenString);
|
||||
}
|
||||
|
||||
public async Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
||||
AuthenticateWithGoogleAsync(GoogleAuthenticationRequest authRequest)
|
||||
{
|
||||
GoogleJsonWebSignature.ValidationSettings settings = new GoogleJsonWebSignature.ValidationSettings();
|
||||
|
||||
settings.Audience = new List<string> { _configuration["Authentication:Google:ClientId"] };
|
||||
|
||||
GoogleJsonWebSignature.Payload payload = GoogleJsonWebSignature.ValidateAsync(authRequest.IdToken, settings).Result;
|
||||
|
||||
var authResponse = new AuthenticationResponse();
|
||||
|
||||
var user = await _userManager.FindByEmailAsync(payload.Email);
|
||||
if (user == null)
|
||||
{
|
||||
var createUserResult = await _userManager.CreateAsync(new User
|
||||
{
|
||||
Email = payload.Email,
|
||||
EmailConfirmed = payload.EmailVerified,
|
||||
FirstName = payload.GivenName,
|
||||
LastName = payload.FamilyName
|
||||
});
|
||||
|
||||
if (!createUserResult.Succeeded)
|
||||
{
|
||||
authResponse.Message = $"{createUserResult.Errors?.First().Description}";
|
||||
return (false, authResponse, null);
|
||||
}
|
||||
}
|
||||
|
||||
string refreshTokenString;
|
||||
|
||||
if (user.RefreshTokens.Any(t => t.IsActive))
|
||||
{
|
||||
var activeRefreshToken =
|
||||
user.RefreshTokens.First(t => t.IsActive);
|
||||
refreshTokenString = activeRefreshToken.Token;
|
||||
authResponse.RefreshTokenExpirationDate = activeRefreshToken.ExpiryDateTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
var refreshToken = CreateRefreshToken();
|
||||
refreshTokenString = refreshToken.Token;
|
||||
authResponse.RefreshTokenExpirationDate = refreshToken.ExpiryDateTime;
|
||||
user.RefreshTokens.Add(refreshToken);
|
||||
await _userManager.UpdateAsync(user);
|
||||
}
|
||||
|
||||
return (true, authResponse, refreshTokenString);
|
||||
}
|
||||
|
||||
public async Task<(bool succeeded, AuthenticationResponse authResponse,
|
||||
string? refreshToken)> RenewRefreshTokenAsync(string? token)
|
||||
{
|
||||
@ -222,7 +285,7 @@ public class AuthenticationService : IAuthenticationService
|
||||
var claims = new[]
|
||||
{
|
||||
new Claim(JwtStandardClaimNames.Sub, user.Id),
|
||||
new Claim(JwtStandardClaimNames.Name, user.LastName + user.FirstName + user.Patronymic),
|
||||
new Claim(JwtStandardClaimNames.Name, $"{user.LastName} {user.FirstName} {user.Patronymic}"),
|
||||
new Claim(JwtStandardClaimNames.GivenName, user.FirstName),
|
||||
new Claim(JwtStandardClaimNames.FamilyName, user.LastName),
|
||||
new Claim(JwtStandardClaimNames.MiddleName, user.Patronymic),
|
||||
|
@ -34,18 +34,11 @@ public class EmailSenderService : IEmailSenderService
|
||||
mailMessage.Subject = $"{applicationName}. {subject}";
|
||||
mailMessage.Body = new TextPart(MimeKit.Text.TextFormat.Text) { Text = message};
|
||||
|
||||
try
|
||||
{
|
||||
await _smtpClient.ConnectAsync(_smtpCredentials.Host, _smtpCredentials.Port, true);
|
||||
await _smtpClient.AuthenticateAsync(Encoding.ASCII, _smtpCredentials.User, _smtpCredentials.Password);
|
||||
await _smtpClient.SendAsync(mailMessage);
|
||||
await _smtpClient.DisconnectAsync(true);
|
||||
return (true, "Letter has been sent successfully");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
await _smtpClient.ConnectAsync(_smtpCredentials.Host, Int32.Parse(_smtpCredentials.Port), false);
|
||||
await _smtpClient.AuthenticateAsync(Encoding.ASCII, _smtpCredentials.User, _smtpCredentials.Password);
|
||||
await _smtpClient.SendAsync(mailMessage);
|
||||
await _smtpClient.DisconnectAsync(true);
|
||||
|
||||
return (true, "Letter has been sent successfully");
|
||||
}
|
||||
}
|
@ -11,6 +11,9 @@ public interface IAuthenticationService
|
||||
|
||||
Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
||||
AuthenticateAsync(AuthenticationRequest authRequest);
|
||||
|
||||
Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
||||
AuthenticateWithGoogleAsync(GoogleAuthenticationRequest authRequest);
|
||||
|
||||
Task<(bool succeeded, AuthenticationResponse authResponse, string? refreshToken)>
|
||||
RenewRefreshTokenAsync(string? token);
|
||||
|
@ -16,6 +16,12 @@
|
||||
"User": "",
|
||||
"Password": ""
|
||||
},
|
||||
"Authentication": {
|
||||
"Google": {
|
||||
"ClientId": "",
|
||||
"ClientSecret": ""
|
||||
}
|
||||
},
|
||||
"Jwt": {
|
||||
"Key": "Secret which will never be exposed",
|
||||
"Audience": "Application URL",
|
||||
|
@ -7,14 +7,21 @@
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Host=localhost;Database=auto.bus;Username=postgres;Password=postgres;"
|
||||
"DefaultConnection": "host=localhost;database=auto.bus;user id=postgres;password=postgres;Include Error Detail = true"
|
||||
},
|
||||
"ApplicationName": "auto.bus",
|
||||
"SmtpCredentials": {
|
||||
"Host": "",
|
||||
"Port": "",
|
||||
"User": "",
|
||||
"Password": ""
|
||||
},
|
||||
"Authentication": {
|
||||
"Google": {
|
||||
"ClientId": "",
|
||||
"ClientSecret": ""
|
||||
}
|
||||
},
|
||||
"Jwt": {
|
||||
"Key": "Secret which will never be exposed",
|
||||
"Audience": "Application URL",
|
||||
|
6
SharedModels/Requests/GoogleAuthenticationRequest.cs
Normal file
6
SharedModels/Requests/GoogleAuthenticationRequest.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace SharedModels.Requests;
|
||||
|
||||
public class GoogleAuthenticationRequest
|
||||
{
|
||||
public string IdToken { get; set; } = null!;
|
||||
}
|
Loading…
Reference in New Issue
Block a user