Skip to content

Commit

Permalink
End of Section 3
Browse files Browse the repository at this point in the history
  • Loading branch information
franconeilglovasa committed Jul 10, 2020
1 parent 319d415 commit 72686b8
Show file tree
Hide file tree
Showing 22 changed files with 1,365 additions and 7 deletions.
6 changes: 6 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
},
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
Expand Down
Binary file not shown.
988 changes: 988 additions & 0 deletions DatingApp.API/.vs/DatingApp.API/config/applicationhost.config

Large diffs are not rendered by default.

Binary file added DatingApp.API/.vs/DatingApp.API/v16/.suo
Binary file not shown.
90 changes: 90 additions & 0 deletions DatingApp.API/Controllers/AuthController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using DatingApp.API.Data;
using DatingApp.API.Dtos;
using DatingApp.API.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;

namespace DatingApp.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
private readonly IAuthRepository _repo;
private readonly IConfiguration _config;
public AuthController(IAuthRepository repo, IConfiguration config)
{
_config = config;
_repo = repo;

}

[HttpPost("register")]
//if you remove apicontroller above
// public async Task<IActionResult> Register([FromBody] UserForRegisterDto userForRegisterDto)
public async Task<IActionResult> Register(UserForRegisterDto userForRegisterDto)
{

//this is for validation if no apicontroller
// if(!ModelState.IsValid)
// return BadRequest(ModelState);

userForRegisterDto.Username = userForRegisterDto.Username.ToLower();
if (await _repo.UserExists(userForRegisterDto.Username))
return BadRequest("Username already exists");

var userToCreate = new User
{
Username = userForRegisterDto.Username
};

var createdUser = await _repo.Register(userToCreate, userForRegisterDto.Password);

return StatusCode(201);
}

[HttpPost("login")]

public async Task<IActionResult> Login(UserForLoginDto userForLoginDto)
{
var userFromRepo = await _repo.Login(userForLoginDto.Username.ToLower(), userForLoginDto.Password);

if (userFromRepo == null)
return Unauthorized();

var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, userFromRepo.Id.ToString()),
new Claim(ClaimTypes.Name, userFromRepo.Username)
};

var key = new SymmetricSecurityKey(Encoding.UTF8
.GetBytes(_config.GetSection("AppSettings:Token").Value));


var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);

var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.Now.AddDays(1),
SigningCredentials = creds
};

var tokenHandler = new JwtSecurityTokenHandler();

var token = tokenHandler.CreateToken(tokenDescriptor);

return Ok(new {
token = tokenHandler.WriteToken(token)
});

}
}
}
3 changes: 3 additions & 0 deletions DatingApp.API/Controllers/ValuesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
using System.Linq;
using System.Threading.Tasks;
using DatingApp.API.Data;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace DatingApp.API.Controllers
{
//http:localhost:5000/api/values

[Authorize]
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
Expand All @@ -30,6 +32,7 @@ public async Task<IActionResult> GetValues()
}

// GET api/values/5
[AllowAnonymous]
[HttpGet("{id}")]

public async Task<IActionResult> GetValues(int id)
Expand Down
81 changes: 81 additions & 0 deletions DatingApp.API/Data/AuthRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System;
using System.Threading.Tasks;
using DatingApp.API.Models;
using Microsoft.EntityFrameworkCore;

namespace DatingApp.API.Data
{
public class AuthRepository : IAuthRepository
{
private readonly DataContext _context;

public AuthRepository(DataContext context)
{
_context = context;

}
public async Task<User> Login(string username, string password)
{
var user = await _context.Users.FirstOrDefaultAsync(x => x.Username == username);

if (user == null)
{
return null;
}

if (!VerifyPasswordHash(password, user.PasswordHash, user.PasswordSalt))
{
return null;
}
return user;

}

private bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
{
using (var hmac = new System.Security.Cryptography.HMACSHA512(passwordSalt))
{
var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
// since computed hash is in byte array, then compare all arrays through for loop
for (int i = 0; i < computedHash.Length; i++)
{
if (computedHash[i] != passwordHash[i]) return false;
}
}
return true;
}

public async Task<User> Register(User user, string password)
{
byte[] passwordHash, passwordSalt;
CreatePasswordHash(password, out passwordHash, out passwordSalt);

user.PasswordHash = passwordHash;
user.PasswordSalt = passwordSalt;

await _context.Users.AddAsync(user);
await _context.SaveChangesAsync();

return user;
}

private void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
{
using (var hmac = new System.Security.Cryptography.HMACSHA512())
{
passwordSalt = hmac.Key;
passwordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
}

}

public async Task<bool> UserExists(string username)
{
if (await _context.Users.AnyAsync(x => x.Username == username))
return true;


return false;
}
}
}
1 change: 1 addition & 0 deletions DatingApp.API/Data/DataContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ public DataContext(DbContextOptions<DataContext> options) : base (options)
}

public DbSet<Value> Values { get; set; }
public DbSet <User> Users { get; set; }
}
}
13 changes: 13 additions & 0 deletions DatingApp.API/Data/IAuthRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Threading.Tasks;
using DatingApp.API.Models;

namespace DatingApp.API.Data
{
public interface IAuthRepository
{
Task<User> Register (User user, string password);
Task<User> Login (string Username, string password);
Task<bool> UserExists (string username);

}
}
3 changes: 3 additions & 0 deletions DatingApp.API/DatingApp.API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.0"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.0"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.0"/>
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="5.6.0"/>
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.6.0"/>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.0"/>
</ItemGroup>
</Project>
9 changes: 9 additions & 0 deletions DatingApp.API/DatingApp.API.csproj.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup>
<ActiveDebugProfile>DatingApp.API</ActiveDebugProfile>
</PropertyGroup>
</Project>
8 changes: 8 additions & 0 deletions DatingApp.API/Dtos/UserForLoginDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace DatingApp.API.Dtos
{
public class UserForLoginDto
{
public string Username { get; set; }
public string Password { get; set; }
}
}
14 changes: 14 additions & 0 deletions DatingApp.API/Dtos/UserForRegisterDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;

namespace DatingApp.API.Dtos
{
public class UserForRegisterDto
{
[Required]
public string Username { get; set; }

[Required]
[StringLength(8, MinimumLength = 4, ErrorMessage = "You must specify password between 4 and 8 characters")]
public string Password { get; set; }
}
}
57 changes: 57 additions & 0 deletions DatingApp.API/Migrations/20200709075644_AddUserEntity.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions DatingApp.API/Migrations/20200709075644_AddUserEntity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;

namespace DatingApp.API.Migrations
{
public partial class AddUserEntity : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Username = table.Column<string>(nullable: true),
PasswordHash = table.Column<byte[]>(nullable: true),
PasswordSalt = table.Column<byte[]>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
});
}

protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Users");
}
}
}
Loading

0 comments on commit 72686b8

Please sign in to comment.