# 2.9: Adding Login Functionality

## Add UserForLogin DTO

In your `Models/User` folder - add another class called `UserForLogin.cs`.

This will be the same as our the register DTO we created earlier. We could use that here - but, we will be making changes later, so it's better to go ahead and have two.

```csharp
public class UserForLogin
{
    public string Username { get; set; }
    public string Password { get; set; }
}
```

## Adding Login Method to Controller

Now we're finally ready to write our `Login()` method.

In this method, we don't need to validate the user's input. If their username and/or passwords don't match - we don't want to give them too much information about what was wrong. We'll just return `Unauthorized()`.

```csharp
[HttpPost("Login")]
public async Task<IActionResult> Login([FromBody] UserForLogin userForLogin)
{
    var userFromDb = await _authService.Login(userForLogin.Username.ToLower(), userForLogin.Password);

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

    //  GENERATE TOKEN
    var tokenHandler = new JwtSecurityTokenHandler();
    var key = new byte[0];                               // we'll add this after adding DI later
    var tokenDescriptor = new SecurityTokenDescriptor    //  Describes information we want to include in our token
    {
        Subject = new ClaimsIdentity(new Claim[]        //  Payload
        {
            new Claim(ClaimTypes.NameIdentifier, userFromDb.Id.ToString()),
            new Claim(ClaimTypes.Name, userFromDb.Username)
        }),
        Expires = DateTime.Now.AddDays(1),
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),
            SecurityAlgorithms.HmacSha512Signature)
    };
    var token = tokenHandler.CreateToken(tokenDescriptor);  //  Create token
    var tokenString = tokenHandler.WriteToken(token);       //  to string (from byte[])

    return Ok( new { tokenString });                        //  Return 200, passing along tokenString
}
```

There is a lot going on here. Some comments have been added to help make it more clear what's going on.

We're getting the user from the database and checking if it's null -- if so, we return `Unauthorized()`.

We're using a `SecurityTokenDescriptor` to format our token - right now we're giving our payload two pieces of information: the Id and username.

We're using `JwtSecurityTokenHandler` to actually create the token with the descriptor we made and also to write it to a string.

## Register Authentication and Add Middleware in Startup Class

Now we need to register our key in our DI container and configure our middleware to use authentication.

In your Startup.cs class add the following to the `ConfigureServices()` method:

```csharp
public void ConfigureServices(IServiceCollection services)
{
    var key = Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value);         // <---- Added
    services.AddDbContext<EFConnectContext>(x => x.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    services.AddMvc();
    services.AddScoped<IAuthService, AuthService>();
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)                              // <---- Added
            .AddJwtBearer(options => {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false
                };
            });
}
```

Next, to add authentication to the middleware - add this *above* the call to `UseMvc()`

```csharp
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    app.UseAuthentication();                //  <---- Added
    app.UseMvc();
}
```

## Adding Key to AuthController and Login() Method

Back in our `AuthController`, we can now access our key.

First, let's inject it into our constructor (remember `ctrl + .` to create a field from parameter):

```csharp
private readonly IConfiguration _config;
public AuthController(IAuthService authService, IConfiguration config)
{
    _config = config;
    _authService = authService;
}
```

Again - we're only injecting interfaces. This is easily swapped out in our Startup class.

Now, we can use this in our `Login()` method:

```csharp
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_config.GetSection("AppSettings:Token").Value);   // <---- Added
var tokenDescriptor = new SecurityTokenDescriptor
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://eleven-fifty-academy.gitbook.io/dotnet-302-core/2-add-users-and-authentication/2.9-adding-login-functionality.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
