Skip to content

Add dotnet user-jwts tool and runtime support #41520

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

Merged
merged 18 commits into from
May 31, 2022

Conversation

captainsafia
Copy link
Member

@captainsafia captainsafia commented May 4, 2022

Part of #39857

❯ dotnet ~/github.com/captainsafia/aspnetcore/artifacts/bin/dotnet-dev-jwts/Debug/net7.0/dotnet-dev-jwts.dll list       
Project: /Users/captainsafia/github.com/AspNetCoreDevJwts/SampleWebApi/SampleWebApi.csproj
User Secrets Id: 17ab27f7-a844-4b14-9f44-a0a363d57fdb
 ---------------------------------------------------------------------------------------------------------------------------- 
 |       Id |         Name |               Audience |                            Issued |                           Expires |
 ---------------------------------------------------------------------------------------------------------------------------- 
 | 394d4cd2 | captainsafia | https://localhost:7157 | 2022-05-05T17:39:23.0000000+00:00 | 2022-11-05T17:39:23.0000000+00:00 |
 ---------------------------------------------------------------------------------------------------------------------------- 
 | 7613954c | captainsafia | https://localhost:7157 | 2022-05-05T22:23:51.0000000+00:00 | 2022-11-05T22:23:50.0000000+00:00 |
 ---------------------------------------------------------------------------------------------------------------------------- 


~/github.com/AspNetCoreDevJwts/SampleWebApi main*
❯ dotnet ~/github.com/captainsafia/aspnetcore/artifacts/bin/dotnet-dev-jwts/Debug/net7.0/dotnet-dev-jwts.dll print --help


Usage: dotnet dev-jwts print [arguments] [options]

Arguments:
  id  The ID of the JWT to print

Options:
  --project    The path of the project to operate on. Defaults to the project in the current directory.
  --show-full  Whether to show the full JWT contents in addition to the compact serialized format
  -h|--help    Show help information


~/github.com/AspNetCoreDevJwts/SampleWebApi main*
❯ dotnet ~/github.com/captainsafia/aspnetcore/artifacts/bin/dotnet-dev-jwts/Debug/net7.0/dotnet-dev-jwts.dll print 7613954c --show-full
Found JWT with ID '7613954c'
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
 |     Name |           Id |               Audience |                           Expires |                            Issued | Scopes | Roles | Custom Claims |                Token Header |                                                                                                                                                                 Token Payload |
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
 | 7613954c | captainsafia | https://localhost:7157 | 2022-11-05T22:23:50.0000000+00:00 | 2022-05-05T22:23:51.0000000+00:00 |        |       |        [none] | {"alg":"HS256","typ":"JWT"} | {"unique_name":"captainsafia","sub":"captainsafia","jti":"7613954c","nbf":1651789430,"exp":1667687030,"iat":1651789431,"iss":"dotnet-dev-jwt","aud":"https://localhost:7157"} |
 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

Compact Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6ImNhcHRhaW5zYWZpYSIsInN1YiI6ImNhcHRhaW5zYWZpYSIsImp0aSI6Ijc2MTM5NTRjIiwibmJmIjoxNjUxNzg5NDMwLCJleHAiOjE2Njc2ODcwMzAsImlhdCI6MTY1MTc4OTQzMSwiaXNzIjoiZG90bmV0LWRldi1qd3QiLCJhdWQiOiJodHRwczovL2xvY2FsaG9zdDo3MTU3In0.0_XltrGVHvHDJSX6GQEk8FzcPSCFB-l04voIg0fk_fo

~/github.com/AspNetCoreDevJwts/SampleWebApi main*
❯ dotnet ~/github.com/captainsafia/aspnetcore/artifacts/bin/dotnet-dev-jwts/Debug/net7.0/dotnet-dev-jwts.dll create --help             


Usage: dotnet dev-jwts create [options]

Options:
  --project     The path of the project to operate on. Defaults to the project in the current directory.
  --name        The name of the user to create the JWT for. Defaults to the current environment user.
  --audience    The audience to create the JWT for. Defaults to the first HTTPS URL configured in the project's launchSettings.json
  --issuer      The issuer of the JWT. Defaults to the dotnet-dev-jwt
  --scope       The issuer of the JWT. Defaults to the dotnet-dev-jwt
  --role        A role claim to add to the JWT. Specify once for each role
  --claim       Claims to add to the JWT. Specify once for each claim in the format "name=value"
  --not-before  The UTC date & time the JWT should not be valid before in the format 'yyyy-MM-dd [[HH:mm[[:ss]]]]'. Defaults to the date & time the JWT is created
  --expires-on  The UTC date & time the JWT should expire in the format 'yyyy-MM-dd [[[[HH:mm]]:ss]]'. Defaults to 6 months after the --not-before date. Do not use this option in conjunction with the --valid-for option.
  --valid-for   The period the JWT should expire after. Specify using a number followed by a period type like 'd' for days, 'h' for hours, 'm' for minutes, and 's' for seconds, e.g. '365d'. Do not use this option in conjunction with the --expires-on option.
  -h|--help     Show help information

@captainsafia captainsafia force-pushed the dev-jwt-tool branch 3 times, most recently from 8fec032 to 0322b72 Compare May 5, 2022 16:54
@Pilchie Pilchie added the area-commandlinetools Includes: Command line tools, dotnet-dev-certs, dotnet-user-jwts, and OpenAPI label May 5, 2022
@captainsafia captainsafia force-pushed the dev-jwt-tool branch 2 times, most recently from 32454fb to f8b6b5d Compare May 5, 2022 22:41
@captainsafia captainsafia requested a review from a team May 5, 2022 22:57
@captainsafia captainsafia marked this pull request as ready for review May 5, 2022 22:58
@captainsafia captainsafia requested review from a team, dougbu, wtgodbe and Pilchie as code owners May 5, 2022 22:58
Copy link
Member

@wtgodbe wtgodbe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build bits look good

@captainsafia
Copy link
Member Author

🆙 📅 :

  • Addressed feedback from above reviews
  • Renamed CLI name to dotnet user-jwts

@captainsafia captainsafia mentioned this pull request May 27, 2022
6 tasks
@captainsafia captainsafia changed the title Add dotnet user-jwts tool Add dotnet user-jwts tool and runtime support May 27, 2022
@@ -166,6 +173,12 @@ private void ConfigureApplication(WebHostBuilderContext context, IApplicationBui
}
}

if (Authentication is WebApplicationAuthenticationBuilder webAuthBuilder && webAuthBuilder.IsAuthenticationConfigured is true)
{
app.UseAuthentication();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to guard this so that the middleware are only added if they're not already added in the app pipeline (like we do with the call to UseRouting() above)? Otherwise we'll be forcing auth to run earlier than the app wants to, which can cause problems, e.g. CORS.

@@ -166,6 +173,12 @@ private void ConfigureApplication(WebHostBuilderContext context, IApplicationBui
}
}

if (Authentication is WebApplicationAuthenticationBuilder webAuthBuilder && webAuthBuilder.IsAuthenticationConfigured is true)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (Authentication is WebApplicationAuthenticationBuilder webAuthBuilder && webAuthBuilder.IsAuthenticationConfigured is true)
if (_webAuthBuilder.IsAuthenticationConfigured)

if (Authentication is WebApplicationAuthenticationBuilder webAuthBuilder && webAuthBuilder.IsAuthenticationConfigured is true)
{
app.UseAuthentication();
app.UseAuthorization();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add something to WebApplicationTests (or another test class since that's already kinda big) to verify we register services and add middleware when methods are called on the WebApplicationAuthenticationBuilder? And another test verifying that just accessing the Authentication getter doesn't do this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, will add this to verify changes for #41520 (comment)

Comment on lines 28 to 32
if (!app.Properties.ContainsKey(AuthenticationMiddlewareSetKey))
{
app.Properties[AuthenticationMiddlewareSetKey] = true;
return app.UseMiddleware<AuthenticationMiddleware>();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check shouldn't be there. The user needs to be able to re-run auth if they add this to the pipeline again.

Copy link
Member

@Tratcher Tratcher May 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would you re-run auth? The AuthN middleware is not route aware and only reacts to the default auth scheme setting.

Copy link
Member

@davidfowl davidfowl May 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's exactly why you'd want to re-run it later in the pipeline to force setting the User based on the default scheme.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess your point is that there's never a situation where running UseAuthentication can change based on where it is in the pipeline. Is that right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well a custom IAuthenticationSchemeProvider doesn't have to return the same value every time, so it is valid that rerunning the authentication middleware could result in a different User being set on a second call

Copy link
Member

@davidfowl davidfowl May 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The performance of auth already sucks, and this doesn't make it better enough to warrant the breaking change.

They can avoid it by not interacting with WebApplicationBuilder.Authentication and instead calling their methods directly on WebApplicationBuilder.

We can still mark that the middleware was added to avoid adding the one in the web application builder.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a flag to let them explicitly turn it off? WebApplicationBuider.Authenticaiton.AutoAddMiddleware = false?

That feels a little strange to me. The WebApplicationBuilder.Authentication pattern is an opt-in to the more simplified approach. It feels weird to have an opt-out to that when the more obvious choice of not using the new Authentication property at all exists.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can someone that wants to manually add the middleware prevent the automatic one?

Our check in the WebApplicationBuilder prevents this from happening. We'll set a flag in UseAuthentication that is read and avoids re-registering automatically in the WAB.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That feels a little strange to me. The WebApplicationBuilder.Authentication pattern is an opt-in to the more simplified approach. It feels weird to have an opt-out to that when the more obvious choice of not using the new Authentication property at all exists.

It feels strange to me that there'd be scenarios we're consciously aware of where we'd say the workaround is to not use the new property. Can we simply make it so that the WebApplicationBuilder does not add the middlewares if the app pipeline has already added the authentication middleware? Why is any more than that needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we simply make it so that the WebApplicationBuilder does not add the middlewares if the app pipeline has already added the authentication middleware? Why is any more than that needed?

It already does that. To clarify, my point was that we didn't need to do anything additional here.

@captainsafia
Copy link
Member Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@captainsafia captainsafia enabled auto-merge (squash) May 31, 2022 22:27
@captainsafia captainsafia merged commit b034a7d into dotnet:main May 31, 2022
@ghost ghost added this to the 7.0-preview6 milestone May 31, 2022
@captainsafia
Copy link
Member Author

/backport release/7.0-preview5

captainsafia added a commit that referenced this pull request May 31, 2022
* Add dotnet dev-jwts tool

* Add dotnet dev-jwts tool

* Address feedback from review

* Rename project file

* Write auth config to app settings

* Address more feedback

* 🦭

* Apply suggestions from code review

Co-authored-by: Brennan <brecon@microsoft.com>

* Address more feedback

* Add framework support for authentication changes

* Add tests for user-jwts CLI and react to feedback

* Move ConsoleTable implementation to avoid conflicts in ProjectTemplates

* Update existing auth tests and fix middleware registration

* Update AzureAdB2C tests and auth app builder

* Fix build and move registration check

* Fix up resolution for Certificate test sources

* Fix write stream configuration for writing key material

* Fix handling missing config section when processing options

Co-authored-by: Brennan <brecon@microsoft.com>
wtgodbe pushed a commit that referenced this pull request Jun 1, 2022
* Add dotnet dev-jwts tool

* Add dotnet dev-jwts tool

* Address feedback from review

* Rename project file

* Write auth config to app settings

* Address more feedback

* 🦭

* Apply suggestions from code review

Co-authored-by: Brennan <brecon@microsoft.com>

* Address more feedback

* Add framework support for authentication changes

* Add tests for user-jwts CLI and react to feedback

* Move ConsoleTable implementation to avoid conflicts in ProjectTemplates

* Update existing auth tests and fix middleware registration

* Update AzureAdB2C tests and auth app builder

* Fix build and move registration check

* Fix up resolution for Certificate test sources

* Fix write stream configuration for writing key material

* Fix handling missing config section when processing options

Co-authored-by: Brennan <brecon@microsoft.com>

Co-authored-by: Brennan <brecon@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-commandlinetools Includes: Command line tools, dotnet-dev-certs, dotnet-user-jwts, and OpenAPI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants