Giter Club home page Giter Club logo

aiof-auth's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

aiof-auth's Issues

Cannot enable a disabled Client

Cannot enable a disabled Client

Reproduction steps

  1. Disable a Client by their id
    image

  2. Try to enable the Client by their id
    image

Root cause analysis
The root cause of this is the query filter applied to on the context level. A disabled client is not returned because the query filter is applied on the get level (when you try to get a client to see if they exist, also why we see the 404 returned).

Support for multiple Roles

Overview
Add support for multiple roles for a user in the JWT. This will include a database changes - schema, etc.

For example, the roles object in the JWT should look like this

{
  "iss": "https://www.jerriepelser.com",
  "aud": "blog-readers",
  "sub": "123456",
  "exp": 1499863217,
  "roles": [ "Admin", "SuperUser" ]
}

Use it as [Authorize(Roles = "")]

public class ValuesController : Controller
{
    [Authorize(Roles = "Admin")]
    [HttpGet("ping/admin")]
    public string PingAdmin()
    {
        return "Pong";
    }
}

Current
The User and Client entities have a RoleId reference (as a foreign key) to the Role entity. This is a one-to-one relationship

Solution
Remove the current relationship between the User, Client and Role entities. Create 2 new entities - UserRole and ClientRole. These will store a one-to-many relationship between a UserId / ClientId and RoleId

Task breakdown
When all tasks are completed, then this will reach the definition of done

  • Create separate UserRole entity that stores UserId and RoleId. Foreign keys from User and Role entities
  • Create separate ClientRole entity that stores ClientId and RoleId. Foreign keys from Client and Role entities
  • Populate UserRole and ClientRole entities and PostgreSQL tables
  • Add functionality to get the many roles stored in the entities
  • Add those claims in the JWT generation and is returned to the end-user
  • Feature flag?
  • Remove RoleId from User entity
  • Remove RoleId from Client entity
  • Add / update unit tests
  • Perform integration tests

OrderBy operator on query

There is a missing OrderBy that makes Entity Framework throw a warning log message when generating a JWT for a user.

image

This warning is appearing even though the following query is setup via LINQ:

public async Task<IUserRefreshToken> GetRefreshTokenAsync(int userId)
{
    return await GetRefreshTokensQuery()
        .Where(x => x.UserId == userId
            && x.Revoked == null)
        .OrderByDescending(x => x.Expires)
        .Take(1)
        .FirstOrDefaultAsync();
}

In this specific example, it essentially checks if there are any existing refresh tokens. If not (the call from this function is null), then create one. Else, return the token

Use RuleSets for TokenRequestValidator

Description

Use FluentValidator RuleSets for TokenRequestValidator. There are a few scenarios that we generate token through

  • Email and password (User)
  • ApiKey (User or Client)
  • Token (User or Client, refresh token)

public class TokenRequestValidator : AbstractValidator<TokenRequest>
{
public TokenRequestValidator()
{
ValidatorOptions.Global.CascadeMode = CascadeMode.Stop;
RuleFor(x => x)
.NotNull();
// Either Email, Password is provided, ApiKey (Client or User) is provided or RefreshToken
RuleFor(x => x)
.Must(x =>
{
if (!string.IsNullOrWhiteSpace(x.Email)
&& !string.IsNullOrWhiteSpace(x.Password)
&& string.IsNullOrWhiteSpace(x.Token)
&& string.IsNullOrWhiteSpace(x.ApiKey))
{
x.Type = TokenType.User;
return true;
}
else if (!string.IsNullOrWhiteSpace(x.ApiKey)
&& string.IsNullOrWhiteSpace(x.Token)
&& string.IsNullOrWhiteSpace(x.Email)
&& string.IsNullOrWhiteSpace(x.Password))
{
x.Type = TokenType.ApiKey;
return true;
}
else if (!string.IsNullOrWhiteSpace(x.Token)
&& string.IsNullOrWhiteSpace(x.Email)
&& string.IsNullOrWhiteSpace(x.Password)
&& string.IsNullOrWhiteSpace(x.ApiKey))
{
x.Type = TokenType.Refresh;
return true;
}
return false;
})
.WithMessage("Invalid token request. Please provide the following: a Email/Password, ApiKey or Token");
}
}

Example

An example of how FluentValidator RuleSets are used is in aiof-asset microservice

https://github.com/kamacharovs/aiof-asset/blob/aae5087522794ce8565b01c442b114c4c053290c/aiof.asset.data/AssetValidator.cs#L71-L99

public AssetDtoValidator(AssetContext context)
{
    ValidatorOptions.Global.CascadeMode = CascadeMode.Stop;

    _context = context ?? throw new ArgumentNullException(nameof(context));

    RuleSet(Constants.AddRuleSet, () => { SetAddRules(); });
    RuleSet(Constants.AddStockRuleSet, () => { SetAddRules(); });

    RuleSet(Constants.UpdateRuleSet, () => { SetUpdateRules(); });
    RuleSet(Constants.UpdateStockRuleSet, () => { SetUpdateRules(); });
}

public void SetAddRules()
{
    RuleFor(x => x.Name)
        .NotEmpty()
        .MaximumLength(100);

    RuleFor(x => x.TypeName)
        .NotEmpty()
        .SetValidator(new AssetTypeValidator(_context));

    RuleFor(x => x.Value)
        .NotNull()
         .GreaterThanOrEqualTo(CommonValidator.MinimumValue)
        .LessThan(CommonValidator.MaximumValue)
        .WithMessage(CommonValidator.ValueMessage);
}

Solution

Set a rule set for each scenario - email & password, api key and token.

public void SetEmailPasswordRuleSet() { }
public void SetApiKeyRuleSet() { }
public void SetTokenRuleSet() { }

For each, we'll then set the .TokenType to the appropriate one and return true. At this point, there is no further logic other than that. However, in the future we might have additional logic to validate each request

General improvements

General improvements to the aiof-auth microservice

  • remove entities' attributes [] such as required, max length, etc. On entities not DTO's
  • add versioning. Similar or same as in aiof-asset
  • (optional) optimize JWT logic

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.