summaryrefslogtreecommitdiff
path: root/backend/Elements.Backend/Controllers
diff options
context:
space:
mode:
authorPaweł Bernaciak <pawelbernaciak@zohomail.eu>2023-10-21 11:55:33 +0200
committerPaweł Bernaciak <pawelbernaciak@zohomail.eu>2023-10-21 11:55:33 +0200
commit12fef7cbaf2073f9cc349ed765ea140be0259d8e (patch)
tree83412d050139bcdbd11eedffa61e1d0c9862dbed /backend/Elements.Backend/Controllers
parent17785848eb53f8d0420f6b6b3be00a0d10be4e1e (diff)
Basic API auth and Google login
Diffstat (limited to 'backend/Elements.Backend/Controllers')
-rw-r--r--backend/Elements.Backend/Controllers/AuthController.cs106
-rw-r--r--backend/Elements.Backend/Controllers/UserController.cs41
-rw-r--r--backend/Elements.Backend/Controllers/WeatherForecastController.cs32
3 files changed, 147 insertions, 32 deletions
diff --git a/backend/Elements.Backend/Controllers/AuthController.cs b/backend/Elements.Backend/Controllers/AuthController.cs
new file mode 100644
index 0000000..56e7c3b
--- /dev/null
+++ b/backend/Elements.Backend/Controllers/AuthController.cs
@@ -0,0 +1,106 @@
+using System.Runtime.Serialization;
+using System.Security.Claims;
+using System.Text.Json;
+using Elements.Data;
+using Elements.Data.Models;
+using Google.Apis.Auth;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Authentication.Cookies;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+
+namespace Elements.Backend.Controllers;
+
+[ApiController]
+[Route("[controller]/[action]")]
+public class AuthController : ControllerBase
+{
+ private readonly IConfiguration _config;
+ private readonly ApplicationDbContext _dbContext;
+
+ public AuthController(IConfiguration config, ApplicationDbContext dbContext)
+ {
+ _config = config;
+ _dbContext = dbContext;
+ }
+
+ public class LoginModel
+ {
+ public required string GoogleToken { get; init; }
+ }
+
+ [HttpPost]
+ public async Task<IActionResult> Login([FromBody] LoginModel model)
+ {
+ GoogleJsonWebSignature.Payload? payload = await VerifyGoogleIdToken(model.GoogleToken);
+ if (payload == null)
+ return Unauthorized();
+
+ User? user = await _dbContext.Users.SingleOrDefaultAsync(u => u.GoogleId == payload.Subject);
+ if (user != null)
+ {
+ //Check if user's name changed and update if it did
+ if (user.Name != payload.Name)
+ user.Name = payload.Name;
+ }
+ else
+ {
+ user = new User()
+ {
+ Name = payload.Name,
+ GoogleId = payload.Subject,
+ Elements = new List<Element>()
+ };
+
+ await _dbContext.Users.AddAsync(user);
+ }
+
+ await _dbContext.SaveChangesAsync();
+
+ List<Claim> claims = new()
+ {
+ new Claim("id", user.Id.ToString()),
+ new Claim(ClaimTypes.Role, "User")
+ };
+ ClaimsIdentity claimsIdentity = new(claims, CookieAuthenticationDefaults.AuthenticationScheme);
+
+ AuthenticationProperties authProperties = new()
+ {
+ IsPersistent = true,
+ AllowRefresh = true
+ };
+
+ await HttpContext.SignInAsync(
+ CookieAuthenticationDefaults.AuthenticationScheme,
+ new ClaimsPrincipal(claimsIdentity),
+ authProperties);
+
+ var response = new
+ {
+ Id = user.Id.ToString()
+ };
+
+ return Ok(JsonSerializer.Serialize(response));
+ }
+
+ [HttpPost]
+ public async Task<IActionResult> Logout()
+ {
+ await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
+ return Ok();
+ }
+
+ private async Task<GoogleJsonWebSignature.Payload?> VerifyGoogleIdToken(string token)
+ {
+ try
+ {
+ GoogleJsonWebSignature.Payload? payload = await GoogleJsonWebSignature.ValidateAsync(token);
+ return payload;
+ }
+ catch (InvalidJwtException)
+ {
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/backend/Elements.Backend/Controllers/UserController.cs b/backend/Elements.Backend/Controllers/UserController.cs
new file mode 100644
index 0000000..bde93aa
--- /dev/null
+++ b/backend/Elements.Backend/Controllers/UserController.cs
@@ -0,0 +1,41 @@
+using System.Security.Claims;
+using System.Text.Json;
+using Elements.Data;
+using Elements.Data.Models;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+
+namespace Elements.Backend.Controllers;
+
+[ApiController]
+[Route("[controller]/[action]")]
+public class UserController: ControllerBase
+{
+ private readonly ApplicationDbContext _dbContext;
+
+ public UserController(ApplicationDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ [HttpGet]
+ [Authorize]
+ [Route("/user/{id:int}")]
+ public async Task<IActionResult> Users(int id)
+ {
+ IEnumerable<Claim> claims = User.Claims;
+ string? currentUserId = claims.FirstOrDefault(claim => claim.Type == "id")?.Value;
+ if (currentUserId == null)
+ return StatusCode(StatusCodes.Status500InternalServerError);
+ if (currentUserId != id.ToString())
+ return Unauthorized();
+
+ User? user = await _dbContext.Users.FirstOrDefaultAsync(user => user.Id == id);
+ if (user == null)
+ return StatusCode(StatusCodes.Status500InternalServerError);
+
+ string userJson = JsonSerializer.Serialize(user);
+ return Ok(userJson);
+ }
+} \ No newline at end of file
diff --git a/backend/Elements.Backend/Controllers/WeatherForecastController.cs b/backend/Elements.Backend/Controllers/WeatherForecastController.cs
deleted file mode 100644
index 9a70e36..0000000
--- a/backend/Elements.Backend/Controllers/WeatherForecastController.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-
-namespace Elements.Backend.Controllers;
-
-[ApiController]
-[Route("[controller]")]
-public class WeatherForecastController : ControllerBase
-{
- private static readonly string[] Summaries = new[]
- {
- "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
- };
-
- private readonly ILogger<WeatherForecastController> _logger;
-
- public WeatherForecastController(ILogger<WeatherForecastController> logger)
- {
- _logger = logger;
- }
-
- [HttpGet(Name = "GetWeatherForecast")]
- public IEnumerable<WeatherForecast> Get()
- {
- return Enumerable.Range(1, 5).Select(index => new WeatherForecast
- {
- Date = DateOnly.FromDateTime(DateTime.Now),
- TemperatureC = Random.Shared.Next(-20, 55),
- Summary = Summaries[Random.Shared.Next(Summaries.Length)]
- })
- .ToArray();
- }
-}