Skip to content

Commit

Permalink
Merge pull request #3 from zijianhuang/OAuth2Yes
Browse files Browse the repository at this point in the history
O auth2 yes
  • Loading branch information
zijianhuang authored Jul 7, 2024
2 parents b1a17a0 + c701b9f commit e30ab15
Show file tree
Hide file tree
Showing 51 changed files with 2,617 additions and 3,707 deletions.
96 changes: 33 additions & 63 deletions AngularHeroes/src/clientapi/WebApiCoreNg2ClientAuto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1544,74 +1544,50 @@ export namespace DemoWebApi_DemoData_Client {

}

export namespace DemoWebApi_Models_Client {
export interface AddExternalLoginBindingModel {

/** Required */
externalAccessToken?: string | null;
}

export interface ChangePasswordBindingModel {

/** Data type: Password */
confirmPassword?: string | null;

/**
* Required
* String length: inclusive between 6 and 100
* Data type: Password
*/
newPassword: string;

/**
* Required
* Data type: Password
*/
OldPwd: string;
export namespace Fonlow_AspNetCore_Identity_Client {
export interface IdentitySeeding {
roles?: Array<string>;
users?: Array<Fonlow_AspNetCore_Identity_Client.UserInitModel>;
}

export interface RegisterBindingModel {

/** Data type: Password */
confirmPassword?: string | null;

/** Required */
export interface UserInitModel extends Fonlow_AspNetCore_Identity_Client.UsernameModel {
email?: string | null;
fullName?: string | null;
role?: string | null;
}

/**
* Required
* String length: inclusive between 6 and 100
* Data type: Password
*/
export interface UsernameModel {
password?: string | null;
username?: string | null;
}

export interface RegisterExternalBindingModel {
}

/** Required */
email?: string | null;
export namespace Fonlow_Auth_Models_Client {
export interface AccessTokenResponse extends Fonlow_Auth_Models_Client.TokenResponseBase {
access_token?: string | null;
expires_in?: number | null;
refresh_token?: string | null;
scope?: string | null;
}

export interface RemoveLoginBindingModel {

/** Required */
loginProvider?: string | null;

/** Required */
providerKey?: string | null;
export interface RefreshAccessTokenRequest extends Fonlow_Auth_Models_Client.RequestBase {
refresh_token?: string | null;
scope?: string | null;
}

export interface SetPasswordBindingModel {
export interface RequestBase {
grant_type?: string | null;
}

/** Data type: Password */
confirmPassword?: string | null;
export interface ROPCRequst extends Fonlow_Auth_Models_Client.RequestBase {
password?: string | null;
scope?: string | null;
username?: string | null;
}

/**
* Required
* String length: inclusive between 6 and 100
* Data type: Password
*/
newPassword?: string | null;
export interface TokenResponseBase {
token_type?: string | null;
}

}
Expand Down Expand Up @@ -1684,16 +1660,10 @@ export namespace Fonlow_WebApp_Accounts_Client {
userId?: string | null;
}

export interface TokenResponseModel {
access_token: string;
export interface TokenResponseModel extends Fonlow_Auth_Models_Client.AccessTokenResponse {
connection_id?: string | null;
expires: string;
expires_in: number;
refresh_token?: string | null;
scope?: string | null;
state?: string | null;
token_type: string;
username: string;
expires?: string | null;
username?: string | null;
}

export interface UserInfoViewModel {
Expand Down
2 changes: 1 addition & 1 deletion AuthDbCreator/CreateBlankMySql.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ $RuntimeId = ([System.Runtime.InteropServices.RuntimeInformation]::RuntimeIdenti
$ExecutableExt = If ($IsWindows) {".exe"} Else {""}
dotnet publish ../Fonlow.EntityFrameworkCore.MySql/Fonlow.EntityFrameworkCore.MySql.csproj -r $RuntimeId --configuration Release --output bin/Release/$netVersion
$connectionString = "server=localhost;port=3306;Uid=root; password=Secured321*; database=DemoAppAuth_Test; Persist Security Info=True;Allow User Variables=true"
$CreatorExe = "AuthDbCreator" + $ExecutableExt;
$CreatorExe = "AuthDbCreator" + $ExecutableExt
Invoke-Expression "&./bin/Release/net8.0/$CreatorExe Fonlow.EntityFrameworkCore.MySql '$connectionString'"
11 changes: 5 additions & 6 deletions Core3WebApi/CodeGen.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
{
"ApiSelections": {
"ExcludedControllerNames": [
"DemoWebApi.Controllers.Polymorphism"
],

"DataModelAssemblyNames": [
"DemoWebApi.DemoDataCore",
"Fonlow.WebApp.Accounts",
"Core3WebApi"
],
"DataModelAssemblyNames": [ "DemoWebApi.DemoDataCore", "Fonlow.WebApp.Accounts", "Fonlow.AspNetCore.Identity", "Core3WebApi" ],
"CherryPickingMethods": 3
},

Expand All @@ -20,6 +16,9 @@
"DataAnnotationsEnabled": true,
"DataAnnotationsToComments": true,
"HandleHttpRequestHeaders": true,
"UseSystemTextJson": true,
"DecorateDataModelWithDataContract": true,
"DataContractNamespace": "http://demoapp.client/2024",

"Plugins": [
{
Expand Down
59 changes: 47 additions & 12 deletions Core3WebApi/Controllers/AuthController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
using System.Security.Claims;
using System.Threading.Tasks;
using WebApp.Utilities;

using Fonlow.Auth.Models;
using System.Net.Http.Headers;
namespace WebApp.Controllers
{

Expand All @@ -24,6 +25,7 @@ namespace WebApp.Controllers
/// </summary>
[ApiExplorerSettings(IgnoreApi = true)]
[Route("token")]
//[ApiController]
public class AuthController : ControllerBase
{
public ApplicationUserManager UserManager
Expand Down Expand Up @@ -52,25 +54,58 @@ public AuthController(ApplicationUserManager userManager, SymmetricSecurityKey s
[AllowAnonymous]
[Consumes("application/x-www-form-urlencoded")]
[HttpPost]
public async Task<ActionResult<TokenResponseModel>> Authenticate([FromForm] UsernameModel model)
public async Task<ActionResult<TokenResponseModel>> Authenticate([FromForm] RequestBase model)
{
ApplicationUser user = await UserManager.FindByNameAsync(model.Username);
if (user == null)
if (model is ROPCRequst)
{
return Unauthorized(new { message = "Username or password is invalid" });
}
ROPCRequst ropcRequest = model as ROPCRequst;
ApplicationUser user = await UserManager.FindByNameAsync(ropcRequest.Username);
if (user == null)
{
return Unauthorized(new { message = "Username or password is invalid" });
}

bool passwordIsCorrect = await UserManager.CheckPasswordAsync(user, model.Password);
if (!passwordIsCorrect)
bool passwordIsCorrect = await UserManager.CheckPasswordAsync(user, ropcRequest.Password);
if (!passwordIsCorrect)
{
return Unauthorized(new { message = "Username or password is incorrect" });
}

var tokenHelper = new UserTokenHelper(UserManager, symmetricSecurityKey, authSettings);
//var newLoginConnectionId = Guid.NewGuid();
return await tokenHelper.GenerateJwtToken(user, ropcRequest.Username, Guid.Empty); //todo: some apps may need to deal with scope
}
else if (model is RefreshAccessTokenRequest refreshAccessTokenRequest)
{
return Unauthorized(new { message = "Username or password is incorrect" });
if (AuthenticationHeaderValue.TryParse(Request.Headers.Authorization, out var headerValue)){
var scehma = headerValue.Scheme;
Debug.Assert("bearer".Equals(scehma, StringComparison.OrdinalIgnoreCase));
var accessToken = headerValue.Parameter;
var jwtSecurityToken = new JwtSecurityTokenHandler().ReadJwtToken(accessToken);
var uniqueNameClaim = jwtSecurityToken.Claims.Single(d => d.Type == "unique_name");
var username = uniqueNameClaim.Value;
var user = await UserManager.FindByNameAsync(username);

if (user == null)
{
return BadRequest(new { message = "Username or password is invalid" });
}

var tokenHelper = new UserTokenHelper(UserManager, symmetricSecurityKey, authSettings);
var tokenTextExisting = await tokenHelper.MatchToken(user, "RefreshToken", refreshAccessTokenRequest.refresh_token, Guid.Empty);
if (!tokenTextExisting)
{
return StatusCode(401, new { message = "Invalid to retrieve token through refreshToken" }); // message may be omitted in prod build, to avoid exposing implementation details.
}

return await tokenHelper.GenerateJwtToken(user, username, Guid.Empty);
}
}

var tokenHelper = new UserTokenHelper(UserManager, symmetricSecurityKey, authSettings);
var newLoginConnectionId = Guid.NewGuid();
return await tokenHelper.GenerateJwtToken(user, model.Username, newLoginConnectionId);
throw new NotSupportedException();
}


/// <summary>
/// Generate new JWT token according to refresh token and connectionId.
/// This call supports AllowAnonymous. So after the access token expires, the client may still acquire new one without login again.
Expand Down
11 changes: 10 additions & 1 deletion Core3WebApi/Controllers/HeroesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
using System.Threading.Tasks;
using Fonlow.DemoApp;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
using Microsoft.AspNetCore.Identity;
using Fonlow.AspNetCore.Identity;

namespace DemoWebApi.Controllers
{
Expand All @@ -19,6 +22,12 @@ namespace DemoWebApi.Controllers
[Authorize(AuthenticationSchemes = ApiConstants.DefaultAuthenticationScheme)]
public class HeroesController : ControllerBase
{
public HeroesController(ApplicationUserManager userManager)
{
this.userManager= userManager;
}

readonly ApplicationUserManager userManager;
/// <summary>
/// Get all heroes.
/// </summary>
Expand Down Expand Up @@ -66,7 +75,7 @@ public Hero PostWithQuery([FromQuery] string name)//.net core difference: requir
}

[HttpPost]
public Hero Post([FromBody] string name)//.net core difference: requires explicit decorattion
public async Task<Hero> Post([FromBody] string name)//.net core difference: requires explicit decorattion
{
var max = HeroesData.Instance.Dic.Keys.Max();
var hero = new Hero { Id = max + 1, Name = name };
Expand Down
92 changes: 92 additions & 0 deletions Core3WebApi/Controllers/PolymorphismController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using Fonlow.Auth.Models;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using System;

namespace DemoWebApi.Controllers
{
/// <summary>
/// For testing different commbinations of parameters and returns
/// </summary>
[Route("api/[controller]")]
public class PolymorphismController : ControllerBase
{
[HttpPost]
[Consumes("application/x-www-form-urlencoded")] //need explicit declaration for sharing endpoint
public async Task<TokenResponseBase> PostTokenRequestAsFormData([FromForm] RequestBase model)
{
if (model.grant_type == "password" && model is ROPCRequst)
{
return new AccessTokenResponse
{
token_type = "bearer",
access_token = "AccessTokenString",
expires_in = 100,
refresh_token = "RefreshTokenString",
Scope = "some scope"
};
}
else if (model.grant_type == "refresh_token" && model is RefreshAccessTokenRequest)
{
return new AccessTokenResponse
{
token_type = "bearer",
access_token = "NewAccessTokenString",
expires_in = 100,
refresh_token = "NewRefreshTokenString",
Scope = "some scope"
};
}

throw new NotSupportedException();
}

//[HttpPost]
//[Consumes("application/json")] //need explicit declaration for sharing endpoint
//public async Task<TokenResponseBase> PostTokenRequest([FromBody] RequestBase model)
//{
// if (model.GrantType == "password" && model is ROPCRequst)
// {
// return new AccessTokenResponse
// {
// TokenType = "bearer",
// AccessToken = "AccessTokenString",
// ExpiresIn = 100,
// RefreshToken = "RefreshTokenString",
// Scope = "some scope"
// };
// }

// throw new NotSupportedException();
//}

//[HttpPost]
//[Route("PostRequestBase")]
//public async Task<RequestBase> PostRequestBase([FromBody] RequestBase model)
//{
// return model;
//}

//[HttpPost]
//[Route("PostROPCRequst")]
//public async Task<ROPCRequst> PostROPCRequst([FromBody] ROPCRequst model)
//{
// return model;
//}

//[HttpPost]
//[Route("PostROPCRequst2")]
//public async Task<RequestBase> PostROPCRequst2([FromBody] ROPCRequst model)
//{
// return model;
//}

//[HttpPost]
//[Route("PostROPCRequst3")]
//public async Task<ROPCRequst> PostROPCRequst3([FromBody] RequestBase model)
//{
// return model as ROPCRequst;
//}

}
}
3 changes: 1 addition & 2 deletions Core3WebApi/Core3WebApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@

<ItemGroup>
<PackageReference Include="Fonlow.DateOnlyExtensions" Version="1.3.0" />
<PackageReference Include="Fonlow.WebApiClientGenCore" Version="7.8.0" />
<PackageReference Include="Fonlow.WebApiClientGenCore" Version="7.8.1" />
<PackageReference Include="Fonlow.WebApiClientGenCore.NG2" Version="4.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="8.0.2" />
</ItemGroup>
Expand Down
Loading

0 comments on commit e30ab15

Please sign in to comment.