Skip to content
This repository has been archived by the owner on Jun 5, 2021. It is now read-only.

Commit

Permalink
feat: auth service
Browse files Browse the repository at this point in the history
  • Loading branch information
arifBurakDemiray committed Jun 4, 2021
1 parent 120d63b commit ceac5c9
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Security/AppSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace SchoolManagament.API.Security
{
public class AppSettings
{
public string Secret { get; set; }
}
}
17 changes: 17 additions & 0 deletions Security/AuthenticationRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;

namespace SchoolManagement.API.Security
{
public class AuthenticationRequest
{
[Required(ErrorMessage = "User Name is required")]
public string Username { get; set; }

[Required(ErrorMessage = "Password is required")]
public string Password { get; set; }
}
}
27 changes: 27 additions & 0 deletions Security/AuthenticationResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using SchoolManagement.API.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace SchoolManagement.API.Security
{
public class AuthenticationResponse
{
public int RoleId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Username { get; set; }
public string Token { get; set; }


public AuthenticationResponse(User user, string token)
{
RoleId = user.RoleId;
FirstName = user.Name;
LastName = user.Surname;
Username = user.Username;
Token = token;
}
}
}
34 changes: 34 additions & 0 deletions Security/AuthorizeAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using SchoolManagement.API.Models;
namespace SchoolManagament.API.Security
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeAttribute : Attribute, IAuthorizationFilter
{
private readonly int _roleID;
public AuthorizeAttribute()
{
_roleID = 0;
}
public AuthorizeAttribute(int roleID)
{
_roleID = roleID;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
var user = (User)context.HttpContext.Items["User"];
if (user == null)
{
// not logged in
context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
}
else if(user.RoleId != _roleID)
{
context.Result = new JsonResult(new { message = "Forbidden" }) { StatusCode = StatusCodes.Status403Forbidden };
}
}
}
}
61 changes: 61 additions & 0 deletions Security/JwtMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SchoolManagament.API.Security
{
public class JwtMiddleware
{
private readonly RequestDelegate _next;
private readonly AppSettings _appSettings;

public JwtMiddleware(RequestDelegate next, IOptions<AppSettings> appSettings)
{
_next = next;
_appSettings = appSettings.Value;
}

public async Task Invoke(HttpContext context, IUserService userService)
{
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();

if (token != null)
attachUserToContext(context, userService, token);

await _next(context);
}

private void attachUserToContext(HttpContext context, IUserService userService, string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,

ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);

var jwtToken = (JwtSecurityToken)validatedToken;
var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value);


context.Items["User"] = userService.GetById(userId);
}
catch
{

}
}
}
}
77 changes: 77 additions & 0 deletions Security/UserSecurity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using SchoolManagement.API.Models;
using SchoolManagement.API.Security;
using SchoolManagement.API.Data;

namespace SchoolManagament.API.Security
{
public interface IUserService
{
AuthenticationResponse Authenticate(AuthenticationRequest model);
IEnumerable<User> GetAll();
User GetById(int id);
}

public class UserService : IUserService
{
// users hardcoded for simplicity, store in a db with hashed passwords in production applications
private readonly IRepo<User> _users;

private readonly AppSettings _appSettings;

public UserService(IOptions<AppSettings> appSettings,IRepo<User> users)
{
_appSettings = appSettings.Value;
_users = users;
}

public AuthenticationResponse Authenticate(AuthenticationRequest model)
{
var users = _users.GetByPredicate(x => x.Username == model.Username && x.Password == model.Password);

//var user = users[0];
// return null if user not found
if (users.Count < 1) return null;

// authentication successful so generate jwt token
var token = generateJwtToken(users[0]);

return new AuthenticationResponse(users[0], token);
}

public IEnumerable<User> GetAll()
{
List<User> users = _users.GetAll().Result;
return users;
}

public User GetById(int id)
{
return _users.GetById(id).Result;
}

// helper methods

private string generateJwtToken(User user)
{
// generate token that is valid for 7 days
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[] { new Claim("id", user.Id.ToString()), new Claim(ClaimTypes.Role, "ADMIN") }),
Expires = DateTime.UtcNow.AddDays(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}
}

0 comments on commit ceac5c9

Please sign in to comment.