Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ASPNET]: 2.9.0 -> Added UserID retrival from nameid, restricted retrival API surface #87

Merged
merged 2 commits into from
Apr 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 25 additions & 10 deletions ChustaSoft.Common.AspNet.UnitTest/ApiControllerBaseTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public void Given_ActionResponseBuilderAndException_When_Ko_Then_IActionResultRe
}

[Test]
public void Given_TokenWithUserId_When_GetRequestUserId_Then_UserId()
public void Given_TokenWithUserId_When_GetRequestUserId_Then_UserIdRetrived()
{
//Arrange
const string expectedUserId = "ff85452f-465b-4539-a056-fd516d635df5";
Expand All @@ -71,22 +71,21 @@ public void Given_TokenWithUserId_When_GetRequestUserId_Then_UserId()
}

[Test]
public void Given_TokenWithUserId_When_GetRequestUserId_With_InvalidClaim_Then_Exception()
public void Given_TokenWithUserIdInnameidClaim_When_GetRequestUserId_Then_UserIdRetrived()
{
//Arrange
const string expectedErrorMessage = "User id cannot be null";
const string expectedUserId = "4c5a0310-8299-4a0b-8eb5-3d9a49a5aa8b";

var testController = CreateTestController(new ControllerContext()
{
HttpContext = CreateHttpContextWithAuthrizationHeader(),
HttpContext = CreateHttpContextWithAuthrizationHeader(IdClaimType.Nameid),
});

//Act
TestDelegate act = () => testController.GetRequestUserId("NonExistingClaim");
var userId = testController.GetRequestUserId();

//Assert
var exception = Assert.Throws<InvalidOperationException>(act);
Assert.AreEqual(exception.Message, expectedErrorMessage);
Assert.AreEqual(userId, expectedUserId);
}

[Test]
Expand Down Expand Up @@ -162,10 +161,19 @@ private TestController CreateTestController(ControllerContext controllerContext
};
}

private DefaultHttpContext CreateHttpContextWithAuthrizationHeader()
private DefaultHttpContext CreateHttpContextWithAuthrizationHeader(IdClaimType idClaimType = IdClaimType.Oid)
{
var httpContext = new DefaultHttpContext();
httpContext.Request.Headers["Authorization"] = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Imwzc1EtNTBjQ0g0eEJWWkxIVEd3blNSNzY4MCIsImtpZCI6Imwzc1EtNTBjQ0g0eEJWWkxIVEd3blNSNzY4MCJ9.eyJhdWQiOiJhcGk6Ly9iNjZjYjc5MS01NWY4LTQ4OGMtODFjNC0yNzM2MjJhODVkNWEiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC80NTMxZDk4NC03M2QwLTQ0MzktYTEwNi00YThhNDRkZGI4YzcvIiwiaWF0IjoxNjMzOTM4NDU2LCJuYmYiOjE2MzM5Mzg0NTYsImV4cCI6MTYzMzk0MjM1NiwiYWNyIjoiMSIsImFpbyI6IkFWUUFxLzhUQUFBQXk3akw3UE0wWGs4azVuSXhMV0ZiRGhoeFIrQ1hORm9BODQvQUVDT1hCVXRzL2l1TTNIQTI0RDl1V25pYVlRa3VzZGRoS2ROdEYyWDZwdnVQRDZoMEVmN3JBTk9SZGJlWG5UWDM2UmZ6cU1zPSIsImFtciI6WyJwd2QiLCJtZmEiXSwiYXBwaWQiOiI2OTI4NDNmOS00N2M2LTQwMTctYjYyNS1mYjJiOTBkZTE1ZDgiLCJhcHBpZGFjciI6IjEiLCJlbWFpbCI6Impvc2UuZWlndXJlbkBjb3RlY25hLmVzIiwiZmFtaWx5X25hbWUiOiJFaWd1cmVuIiwiZ2l2ZW5fbmFtZSI6Ikpvc2UiLCJpcGFkZHIiOiI5MC4xNzMuMTQ3LjEwOCIsIm5hbWUiOiJFaWd1cmVuIEpvc2UiLCJvaWQiOiJmZjg1NDUyZi00NjViLTQ1MzktYTA1Ni1mZDUxNmQ2MzVkZjUiLCJvbnByZW1fc2lkIjoiUy0xLTUtMjEtNjA2NzQ3MTQ1LTE5NTc5OTQ0ODgtODM5NTIyMTE1LTI4NzM3IiwicmgiOiIwLkFZRUFoTmt4UmRCek9VU2hCa3FLUk4yNHhfbERLR25HUnhkQXRpWDdLNURlRmRpQkFDSS4iLCJzY3AiOiJwYXJraW5nX2FwaV9hY2Nlc3MiLCJzaWQiOiJlOTU3YzEzOC00NmU4LTQwMjAtYjI3My1mM2Q0N2RiNTFjNjYiLCJzdWIiOiJSQkpLWlFPTDRuQjZCME5pSGVHblFlVFpVWkVNUTJTN01PMnpUYU1ISXpjIiwidGlkIjoiNDUzMWQ5ODQtNzNkMC00NDM5LWExMDYtNGE4YTQ0ZGRiOGM3IiwidW5pcXVlX25hbWUiOiJqb3NlLmVpZ3VyZW5AY290ZWNuYS5lcyIsInVwbiI6Impvc2UuZWlndXJlbkBjb3RlY25hLmVzIiwidXRpIjoiS2V6SWhjTkM5a2VILURiaTRPN0lBQSIsInZlciI6IjEuMCJ9.MIfNYBb1_--GgHZM7-9JFd6mUjhU_Os-3CU8HToFn8rJc8IzFS0BgfJMLTn730YVYNYSfwFr8JGt5ISHdHkorFJdAi7jY6n_hESCK0uyC1jcXjiKgeMOP-8OMZ2OXGHbu_-e0Qb4ujUGrdWygSKfyv6kWH5-weLZjWv8I2mN0cdmotbNDbygyI6GJa9kPEEoQNkzxxLu-9yzpk7HKIV9BXL3KV1-XErRoDhKFJiaxlQooKTlxzjqaGoUVu7gTKdXHmOXJBdObhJIaaKBVcaW66iYM391LlVLK2hIahJ6YHXoyiwmySWBObHyP0mmfNRv6hrst_l77y8ax71DtSNe8Q";

switch (idClaimType)
{
case IdClaimType.Oid:
httpContext.Request.Headers["Authorization"] = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Imwzc1EtNTBjQ0g0eEJWWkxIVEd3blNSNzY4MCIsImtpZCI6Imwzc1EtNTBjQ0g0eEJWWkxIVEd3blNSNzY4MCJ9.eyJhdWQiOiJhcGk6Ly9iNjZjYjc5MS01NWY4LTQ4OGMtODFjNC0yNzM2MjJhODVkNWEiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC80NTMxZDk4NC03M2QwLTQ0MzktYTEwNi00YThhNDRkZGI4YzcvIiwiaWF0IjoxNjMzOTM4NDU2LCJuYmYiOjE2MzM5Mzg0NTYsImV4cCI6MTYzMzk0MjM1NiwiYWNyIjoiMSIsImFpbyI6IkFWUUFxLzhUQUFBQXk3akw3UE0wWGs4azVuSXhMV0ZiRGhoeFIrQ1hORm9BODQvQUVDT1hCVXRzL2l1TTNIQTI0RDl1V25pYVlRa3VzZGRoS2ROdEYyWDZwdnVQRDZoMEVmN3JBTk9SZGJlWG5UWDM2UmZ6cU1zPSIsImFtciI6WyJwd2QiLCJtZmEiXSwiYXBwaWQiOiI2OTI4NDNmOS00N2M2LTQwMTctYjYyNS1mYjJiOTBkZTE1ZDgiLCJhcHBpZGFjciI6IjEiLCJlbWFpbCI6Impvc2UuZWlndXJlbkBjb3RlY25hLmVzIiwiZmFtaWx5X25hbWUiOiJFaWd1cmVuIiwiZ2l2ZW5fbmFtZSI6Ikpvc2UiLCJpcGFkZHIiOiI5MC4xNzMuMTQ3LjEwOCIsIm5hbWUiOiJFaWd1cmVuIEpvc2UiLCJvaWQiOiJmZjg1NDUyZi00NjViLTQ1MzktYTA1Ni1mZDUxNmQ2MzVkZjUiLCJvbnByZW1fc2lkIjoiUy0xLTUtMjEtNjA2NzQ3MTQ1LTE5NTc5OTQ0ODgtODM5NTIyMTE1LTI4NzM3IiwicmgiOiIwLkFZRUFoTmt4UmRCek9VU2hCa3FLUk4yNHhfbERLR25HUnhkQXRpWDdLNURlRmRpQkFDSS4iLCJzY3AiOiJwYXJraW5nX2FwaV9hY2Nlc3MiLCJzaWQiOiJlOTU3YzEzOC00NmU4LTQwMjAtYjI3My1mM2Q0N2RiNTFjNjYiLCJzdWIiOiJSQkpLWlFPTDRuQjZCME5pSGVHblFlVFpVWkVNUTJTN01PMnpUYU1ISXpjIiwidGlkIjoiNDUzMWQ5ODQtNzNkMC00NDM5LWExMDYtNGE4YTQ0ZGRiOGM3IiwidW5pcXVlX25hbWUiOiJqb3NlLmVpZ3VyZW5AY290ZWNuYS5lcyIsInVwbiI6Impvc2UuZWlndXJlbkBjb3RlY25hLmVzIiwidXRpIjoiS2V6SWhjTkM5a2VILURiaTRPN0lBQSIsInZlciI6IjEuMCJ9.MIfNYBb1_--GgHZM7-9JFd6mUjhU_Os-3CU8HToFn8rJc8IzFS0BgfJMLTn730YVYNYSfwFr8JGt5ISHdHkorFJdAi7jY6n_hESCK0uyC1jcXjiKgeMOP-8OMZ2OXGHbu_-e0Qb4ujUGrdWygSKfyv6kWH5-weLZjWv8I2mN0cdmotbNDbygyI6GJa9kPEEoQNkzxxLu-9yzpk7HKIV9BXL3KV1-XErRoDhKFJiaxlQooKTlxzjqaGoUVu7gTKdXHmOXJBdObhJIaaKBVcaW66iYM391LlVLK2hIahJ6YHXoyiwmySWBObHyP0mmfNRv6hrst_l77y8ax71DtSNe8Q";
break;
case IdClaimType.Nameid:
httpContext.Request.Headers["Authorization"] = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6InRlc3RAbWFpbC5jb20iLCJuYW1laWQiOiI0YzVhMDMxMC04Mjk5LTRhMGItOGViNS0zZDlhNDlhNWFhOGIiLCJlbWFpbCI6InRlc3RAbWFpbC5jb20iLCJyb2xlIjpbIlN5c3RlbSBBZG1pbiIsIlN1cGVyIEFkbWluIl0sImN1bHR1cmUiOiJlbi1VSyIsInN1YiI6InRlc3RAbWFpbC5jb20iLCJqdGkiOiIxYWJhNmU5NS1kNTlmLTRlM2QtODBmMi1kODIxMTRjMWY2NDQiLCJhdWQiOiJjb3RlY25hLmVzIiwiaXNzIjoiY290ZWNuYS5lcyIsIm5iZiI6MTY4MjQ5MDQ3OSwiZXhwIjoxNjgzMDk1Mjc5LCJpYXQiOjE2ODI0OTA0Nzl9.JLidtcuqp_VDi_paX05HRT68ekawGtZTvC4Mjw3IZcg";
break;
}

return httpContext;
}
Expand Down Expand Up @@ -221,4 +229,11 @@ internal IActionResult Expose_Ko<T>(ActionResponseBuilder<T> actionResponseBuild
}

}
}


internal enum IdClaimType
{
Oid,
Nameid
}
}
6 changes: 3 additions & 3 deletions ChustaSoft.Common.AspNet/ChustaSoft.Common.AspNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
<Authors>Xelit3</Authors>
<Company>ChustaSoft</Company>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<Version>2.8.0</Version>
<FileVersion>2.8.0</FileVersion>
<AssemblyVersion>2.8.0</AssemblyVersion>
<Version>2.9.0</Version>
<FileVersion>2.9.0</FileVersion>
<AssemblyVersion>2.9.0</AssemblyVersion>
<PackageProjectUrl>https://github.com/ChustaSoft/CommonNET</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/ChustaSoft/CommonNET/blob/main/LICENSE</PackageLicenseUrl>
<RepositoryUrl>https://github.com/ChustaSoft/CommonNET.git</RepositoryUrl>
Expand Down
18 changes: 7 additions & 11 deletions ChustaSoft.Common.AspNet/Extensions/ControllerBaseExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,22 @@ public static class ControllerBaseExtensions
{

private const string ACCESS_TOKEN_HEADER = "Authorization";
private const string OID_CLAIM = "oid";



/// <summary>
/// Gets the user id from the autorization token header
/// </summary>
/// <param name="controllerBase">Controller from wich get the information</param>
/// <param name="userIdClaim">Claim where the userd id is located</param>
/// <returns>User id found in the access token authorization header</returns>
public static string GetRequestUserId(this ControllerBase controllerBase, string userIdClaim = OID_CLAIM)
public static string GetRequestUserId(this ControllerBase controllerBase)
{
var jwt = controllerBase.GetTokenFromAuthHeader();
var userId = jwt.Claims.FirstOrDefault(x => x.Type.Equals(userIdClaim, StringComparison.OrdinalIgnoreCase))?.Value;

if (string.IsNullOrEmpty(userId))
{

return
jwt.Claims.FirstOrDefault(c => c.Type.Equals("oid", StringComparison.OrdinalIgnoreCase))?.Value ??
jwt.Claims.FirstOrDefault(c => c.Type.Equals("nameid", StringComparison.OrdinalIgnoreCase))?.Value ??
throw new InvalidOperationException("User id cannot be null");
}

return userId;
}

/// <summary>
Expand Down Expand Up @@ -59,7 +55,7 @@ private static IEnumerable<Claim> GetClaims(this ControllerBase controllerBase)
return controllerBase.GetTokenFromAuthHeader().Claims;
}

private static JwtSecurityToken GetTokenFromAuthHeader(this ControllerBase controllerBase)
public static JwtSecurityToken GetTokenFromAuthHeader(this ControllerBase controllerBase)
{
var accessToken = controllerBase.Request.Headers[ACCESS_TOKEN_HEADER].FirstOrDefault()?.Split(" ")[1];
var jwt = new JwtSecurityTokenHandler().ReadToken(accessToken) as JwtSecurityToken;
Expand Down
4 changes: 4 additions & 0 deletions ChustaSoft.Common.AspNet/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## [2.9.0] - 2023-04-26
### Added
- Restricted the UserID retrieval masking the logic only for oid and nameid

## [2.8.0] - 2022-12-20
### Added
- Support for .NET 7.0
Expand Down