Skip to content

Commit

Permalink
Merge pull request #107 from madeyoga/v2.2
Browse files Browse the repository at this point in the history
HttpOnlyCookie option
  • Loading branch information
madeyoga authored Sep 24, 2022
2 parents 580f6ce + e51c5c3 commit ef09a59
Show file tree
Hide file tree
Showing 157 changed files with 7,062 additions and 1,780 deletions.
7 changes: 2 additions & 5 deletions Documentation/wiki/endpoints/definitions.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
### Implementing your own Endpoint Definition
### Using IEndpointDefinition

You can define your own minimal api endpoint definition by implementing the `IEndpointDefintion` inerface.
You can define your own minimal api endpoint definition by implementing the `IEndpointDefintion` interface.

```cs
internal class MyEndpointsDefinition : IEndpointDefinition
Expand All @@ -20,9 +20,6 @@ internal class MyEndpointsDefinition : IEndpointDefinition
Add your endpoint definition

```cs
var endpointsBuilder = builder.Services.AddAuthEndpointsCore<string, IdentityUser>();
endpointsBuilder.AddJwtEndpoints();

builder.Services.AddEndpointDefinition<MyEndpointDefinition>(); // <--
var app = builder.Build();
Expand Down
20 changes: 8 additions & 12 deletions Documentation/wiki/get-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ Install-Package AuthEndpoints

## Quick Start

First, let's install `Microsoft.AspNetCore.Identity.EntityFrameworkCore` and create a DbContext:

```
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
```
First, let's create a DbContext:

```cs
// Data/MyDbContext.cs
Expand Down Expand Up @@ -71,10 +67,10 @@ Next, let's add auth endpoints services:
```cs
// Program.cs
// Add basic authentication endpoints
// Add users api endpoints
builder.Services
.AddAuthEndpointsCore<IdentityUser, MyDbContext>() // <--
.AddBasicAuthenticationEndpoints()
.AddUsersApiEndpoints()
.Add2FAEndpoints();

// Add JWT endpoints
Expand Down Expand Up @@ -102,9 +98,9 @@ app.MapEndpoints(); // <--
app.Run();
```

Run it and you should see auth endpoints available on swagger docs!
Run it and you should see endpoints available on swagger docs!

![authendpoints swagger](https://i.imgur.com/VCuIazI.png "authendpoints swagger")
![authendpoints swagger](https://i.imgur.com/rqMbFNy.png "authendpoints swagger")


## Full Source Code
Expand Down Expand Up @@ -137,10 +133,10 @@ builder.Services
.AddEntityFrameworkStores<MyDbContext>() // <-- Microsoft.AspNetCore.Identity.EntityFrameworkCore
.AddDefaultTokenProviders(); // <--
// Add basic authentication
// Add Users API
builder.Services
.AddAuthEndpointsCore<IdentityUser>() // <--
.AddBasicAuthenticationEndpoints()
.AddUsersApiEndpoints()
.Add2FAEndpoints();

// Add JWT endpoints
Expand Down Expand Up @@ -171,6 +167,6 @@ app.Run();
## Available Endpoints
Checkout endpoints definition [docs](endpoints/definitions.md)

- [Basic authentication endpoints](endpoints/basic-authentication.md)
- [Users endpoints](endpoints/base-endpoints.md)
- [JWT endpoints](endpoints/jwt.md)
- [2FA endpoints](endpoints/2fa.md)
4 changes: 2 additions & 2 deletions Documentation/wiki/toc.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# [Get Started](get-started.md)
# [Supported Endpoints](endpoints/basic-authentication.md)
## [Base Endpoints](endpoints/basic-authentication.md)
# [Supported Endpoints](endpoints/base-endpoints.md)
## [Base Endpoints](endpoints/base-endpoints.md)
## [Jwt Endpoints](endpoints/jwt.md)
## [2FA Endpoints](endpoints/2fa.md)
# [Endpoint Definition](endpoints/definitions.md)
Expand Down
66 changes: 60 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

A simple jwt authentication library for ASP.Net 6. AuthEndpoints library provides a set of Web API controllers and minimal api endpoints to handle basic web & JWT authentication actions such as registration, email verification, reset password, create jwt, etc. It works with [custom identity user model](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/customize-identity-model?view=aspnetcore-6.0#custom-user-data). AuthEndpoints is built with the aim of increasing developer productivity.

![swagger_authendpoints](https://i.imgur.com/rqMbFNy.png)

## Supported endpoints
- Basic authentication actions:
- Users API:
- sign-up
- email verification
- user profile (retrieving)
Expand All @@ -27,7 +29,6 @@ A simple jwt authentication library for ASP.Net 6. AuthEndpoints library provide

## Current limitations
- Only works with IdentityUser or custom identity user
- No session based auth support
- 2fa via email

## Installing via NuGet
Expand Down Expand Up @@ -60,24 +61,38 @@ public class MyDbContext : IdentityDbContext
}
```

Add migration and apply migration:

```
// using dotnet cli
$ dotnet ef migrations add CreateRefreshToken
$ dotnet ef database update
// or using package manager console in visual studio
PM> Add-Migration CreateRefreshToken
PM> Update-Database
```

Add endpoints and call `app.MapEndpoints()` before `app.Run();`

```cs
// Program.cs

// Required services
builder.Services.AddIdentityCore<IdentityUser>(); // <--
// Add core & basic authentication endpoints
// Add core services & users api
builder.Services.AddAuthEndpointsCore<IdentityUser, MyDbContext>() // <--
.AddBasicAuthenticationEndpoints()
.AddUsersApiEndpoints()
.Add2FAEndpoints();

// Add jwt endpoints
// When no options are provided
// AuthEndpoints will create a secret key and use a single security key (symmetric encryption)
// for each access jwt and refresh jwt.
// Secrets will be created under `keys/` directory.
builder.Services.AddSimpleJwtEndpoints<IdentityUser, MyDbContext>();
builder.Services.AddSimpleJwtEndpoints<IdentityUser, MyDbContext>(); // <--
var app = builder.Build();

Expand All @@ -93,7 +108,46 @@ app.MapEndpoints(); // <--
app.Run();
```

Checkout [docs](https://madeyoga.github.io/AuthEndpoints/wiki/get-started.html) for more info.
Jwt endpoints (registered by `AddSimpleJwtEndpoints<,>()`) will return the access and refresh tokens to the client.
During the authentication flow, we save the access and refresh tokens on the client storage, for instance web storage (localStorage / sessionStorage).
We'll then attach the access token to the HTTP client on every request against the API.
This approach does not require any backend for SPA hosting, so the SPA can be standalone. There is no SameSite requirement.
Another advantage of this approach is its contents cannot be automatically sent anywhere. Therefore, immune to cross-site request forgery (CSRF) attacks.
In short, token storage and handling are all done on client side.

On the downside, this default approach often adds a level of complexity with potential security concerns.
Let's say we store the tokens in web storage.
Any JavaScript running on our site will have access to web storage.
This make the tokens can be easily grabbed via cross-site scripting (XSS) attacks.

To avoid this issue, you might consider storing jwts inside httponly cookie. This adds a layer of protection to the jwts.
HttpOnly flag on cookie mitigate the risk of client side script accessing the protected cookie.
With this approach, token storage and handling are all done at the backend side.

To use this approach, you can simply:

```cs
builder.Services.AddSimpleJwtEndpoints<IdentityUser, MyDbContext>(options =>
{
options.UseCookie = true;
});
```

When using `UseCookie = true`, jwts will be stored in httponly cookie with samesite set to lax by default. All jwt endpoints will return 204 NoContent
instead of returning the access and refresh tokens to the client as json (tokens are no longer handled at the client side).

Keep in mind that storing jwts inside HttpOnly Cookie does not prevent XSS attacks.
XSS basically means somebody can remotely run js code on our site.
This has nothing to do with whether the token is stored in web storage or whether its stored in httponly cookie.
If site is vulnerable to XSS, with httponly cookie, attacker cannot grab the tokens.
However, attacker can still make a request on of behalf of the user.
You must always follow best practices against XSS including escaping contents.

Cookie is considered more secure, but it might be vulnerable to cross-site request forgery (CSRF) attacks.
Antiforgery is not handled by default and so you might need some custom code to flow a CSRF token between the server and your client application.

### Which approach should you use?
Most of the times you may want to store JWTs in HttpOnly Cookie. It makes development process easier and considered more secure because tokens are no longer handled at the client side.

## Documentations
Documentation is available at [https://madeyoga.github.io/AuthEndpoints/](https://madeyoga.github.io/AuthEndpoints/) and in [docs](https://github.com/madeyoga/AuthEndpoints/tree/main/docs) directory.
Expand Down
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

| Version | Supported |
| ------- | ------------------ |
| 2.0.1 | :white_check_mark: |
| < 2.0.1 | :x: |
| 2.2 | :white_check_mark: |
| < 2.2 | :x: |

## Reporting a Vulnerability

Expand Down
Loading

0 comments on commit ef09a59

Please sign in to comment.