Implementing API Key Authentication in ASP.NET Core
Вставка
- Опубліковано 6 вер 2024
- Check out my courses: dometrain.com
Become a Patreon and get source code access: / nickchapsas
Hello everybody I'm Nick and in this video I will show you all the approaches you can use to add API Key based authentication in you ASP.NET Core APIs. I will cover a generic approach and then Controller and Minimal API specific approaches and also show you how you can add Open API support for Swagger.
Workshops: bit.ly/nickwor...
Don't forget to comment, like and subscribe :)
Social Media:
Follow me on GitHub: bit.ly/ChapsasG...
Follow me on Twitter: bit.ly/ChapsasT...
Connect on LinkedIn: bit.ly/ChapsasL...
Keep coding merch: keepcoding.shop
#csharp #dotnet
I love your videos, you are so professional, but i would really love and appreciate if you make a small app, that shows us how yo implement all the best practices you teach us, I mean I learn tbd concept from you, and I always go and implement it in my projects, but sometimes I get lost in the implementation. If you can just do a todo list api, with all the consepts, like rest API rules, versioning, SOLID, services, mapping, results, responses. Thank you very much for the great content 🙏
That would be a GREAT COURSE and I would totally buy it
Yes
@@juliansegura5507same
Agree... would be the best course ever
Hi Nick I love your videos so very much!
*Hint* You probably already know this, but rather than using the Generate Guid tool (which means moving hand to mouse etc.) you can just type "nguid [tab]" and Rider will allow you to insert a new guid and even select the version without dashes. :) Keep up the great work mate!
I DIDNT KNOW THAT OH MY GOD THATS SO COOL!!!
Wait... WHAT???
I need to try Rider ASAP!
This also works with JetBrains Resharper in Visual Studio.
Thanks, didn't know about this 😉
@@nickchapsas `!apiKey.Equals(expectedApiKey)`. This is prone to timing-attack. Secrets should be compared in constant time.
I would love to see examples using OAuth 2 Client Credentials flow (using an IDP service like Okta or Auth0) where the APIs accept a valid bearer token.
Thanks for the awesome video.
Would be very interesting to see JWT Bearer auth with refresh tokens as well.
Agreed. Would be nice to see best approaches to implement OIDC or just oauth.
There already is a video from Nick about it here ua-cam.com/video/M6AkbBaDGJE/v-deo.html
Yeah! And how would you protect against a replay attack? Or is it even necessary to worry about this?
To get rid of [ServiceFilter(typeof(...)] thing you can derive from ServiceFilterAttribute and provide default ctor with :base (typeof(ApiKeyAuthFilterImpl)). Then you can use your filter directly (ApiKeyAuthFilterImpl is actual implementation of filter, must be registered in DI container)
Good suggestion! For the longest time I thought the attribute was sealed, but you are right, it isn't!
Id love to see example of storing multiple API Keys in database and comparing the header key to those in the database. I have a scenario where I will have multiple clients using the API and would like to have a different API Key to give them access to their own data. Great video !
To get around the dependency injection problem you can create a custom attribute that extends from TypeFilterAttribute, which then passes typeof(MyFilter) to the base constructor. From there the system will allow you to use DI in your filter.
public class FooAttribute : TypeFilterAttribute
{
public FooAttribute() : base(typeof(FooFilter)) { }
private class FooFilter : IActionFilter
{
private readonly IConfiguration _config;
public FooFilter(IConfiguration config) // inject anything here
{
_config = config;
}
public void OnActionExecuting(ActionExecutingContext context) { ... }
public void OnActionExecuted(ActionExecutedContext context) { ... }
}
}
And now you can apply [FooAttribute] to anything and have, for example, IActionFilter with Dependency Injection
Thank you Nick! This video greatly helped me. You covered all aspects, including the Swagger which I was struggling with. Thank you 🙏
i always copy/paste some example from the internet and i never stop to think how it works because the explanation is almost always just technical terms and blah blah hard to understand
your explanation is without a doubt simple, objective and easy to understand, thank you very much
Great video Nick, as always! A tip to others: the same principal can be used to enforce client certificate based auth, minus the Swagger UI integration. This way, you can easily enforce different types of auth on different scopes within the same API.
Great help, exactly what I needed. Thanks tons. Since adopting Blazor Server then finding Minimal API's I can now build Api's without MVC "and" secure them. I remember first hearing of WebSocket so many years ago, throw in Entra, Microsoft Graph, and Application Proxy we now have flying cars for the enterprise.
Extremely interested in the way you presented and covered different approaches. Thanks bro
I finally can understand this concept to it's fullest. Thanx for the great content
This is exactly what I was lookinf for to use in my current project. Well done on providing such great content; clean, concise and easy to follow.
the longest app. 18 minutes in my life :D thank you for the explanation!
Hi Nick, thanks for the video, good content as usual! You mentioned the attribute usage and DI issue. ApiKeyAuthFilter class can be as it is but creating a new attribute, makes it work.
public class ApiKeyAuthFilterAttribute : ServiceFilterAttribute {
public ApiKeyAuthFilterAttribute() : base(typeof(ApiKeyAuthFilter)) { }
}
services.AddScoped();
Thanks Nick for the video, awesome as usual !
What is your thought about `AddScheme` and `AuthenticationHandler` ? or the `AddAuthorization` and `AddPolicy` ?
It's a bit of a more convoluted approach which is why I prefer the ones that I show in the video. They are way more straightfoward.
I agree with you, I had a hard time implementing them ^^
Hi Nick, I had to add mixed authorization: Bearer header as well as ApiKey header. I did it using the methods mentioned in the comment above. I have source code if you wanna see it. I was actually hoping this video would show us a better way of adding mixed authorization. Thank you as always, amazing work.
AND then I had to mix in jwt/bearer authorization for signalR in the query string instead of header :)
@@benjaminboyle3295 This video is exclusive to API Key authentication as the name implies. I've covered mixed auth in the past. It might be something I re-visit in the future
Thank you, very useful auth concept. Was just looking for something like it
This help me a lot, very well explained. Thank you !
one of your best videos so far 👌🏻
You saved me hours of training,
Thank you very much for your hard work
Please do a video on task ConfigureAwait(). It's so confusing
Would love a video on building a throttle mechanism where its not waiting in memory but in a queue or database
Hi Nick! First of all thank you very much for your videos! They are soooo interesting and you actually taught me a lot since when I started following you :D
I have a question about this approach: why yoi didn't mention the AuthenticationHandler approach?
Tak! Brilliant video! Covers all my thoughts and questions about API Keys in one video!
damn nice timing, Milan Jovanovixc released video on the same topic few days ago :D
Oh did he? Nice! I don't follow him so I wouldn't know, I plan my videos weeks in advance.
Thank you for the simple to follow exampesl!
a lot of good tips =) Thanks Nick!
Hi Nick, i love your videos - and this is one is especially great. In this short video you have explained so many things in a clear and concise way. Its great!!
Awesome video, thanks. very useful & just what I was looking for.
Am I crazy? I’ve always found the swagger ui has the lock icons mixed up. Why would the lock be LOCKED when the api is unlocked and authorized for use??
What is a good place to store secrets (like API keys etc) for on-premise services, hosted on IIS, that don't have access to any cloud solutions, like Azure/AWS key vaults?
Briefly: any separate server within your org network, data center, etc but you have to provide security, access control, physical security,etc
Hope it will help! :)
have you found somewhere the answer? can you share this?
This was exactly what I needed. Now maze makes way more sense!
This video is a gem!
You could also have a class extending ServiceFilterAttribute so you can have DI in you Authorization Filter.
Thats awesome! But what about implemeting an AuthenticationHandler for ApiKey scheme and then register that in AuthenticationBuilder ? I think AuthenticationHandler is the best option.
It’s the most convoluted option for something that can be as simple as shown in the video. I don’t like that approach for this use case
Thank you, very interesting and easy to implement with your clear details. Looks appropriate for a use case I have.
Couple of questions 😁
- Can you safely mix auth schemes, i.e I have a multi-tenant minimal api that users authenticate to via Azure B2C oauth2, but I need to add a simple API key access for a few endpoints, for service apps to use. I could use client credentials flow or application api's, but there's the problem of distributing/revoking api keys and I want to issue them dynamically depending on the tenant the service apps belong to.
- Can you restrict access to a SignalR server using these?
- Swagger - can it handle multiple auth schemes?
To answer part of my own question - yup, Swagger UI can handle multiple auth types, you get the option to choose which one when Autherising. Works the best. And you can mix auth schemes.
Nick, at times I just think you're reading my mind. I was just building this out for work and needed a refresh because I haven't done it in a while.
Helped a loot, thank you. Gona subscribe to your channel. Nice work!
Very good and detailed explination on this topic, great video!
Great video! Thank you very much, Nick!
Could you please tell us about cases where 2 authentication schemes are used at the same time, for example ApiKey together with JWT. For example a case where I have 2 clients for my API, a web app and a mobile app. How to properly design the api in such a case?
Nick You are .Net Rockstar! Thank you!
Fantastic! Thank you! Clear and precise! Very Good!
Great video! Thanks a lot for your efforts, Nick! You're great
Amazing video! I always learn so much from your content 😎👍
thank you we love you
Awesome video as always Nick!
Hi, can you come up with a vidwo where you can demonstrate how to Authorize same endpoint using either inbuilt jwt bearer or api key at the same time? So,how we can add custom authentication along with inbuilt authentication schemes and regiater at startup. Thanks
Hi Nick, appreciate the work you do. One question about the filter of the minimal api. If we have another middleware the request stops first in it and then into the filter?
Great video. Superb content. Thank you !!!
Thanks Nick, i need this
That's great explanation. Thanks.
Great job as always. Thanks dude
I was hoping to use api keys with Identity framework, I recall seeing your .NET core 2 & 3 playlist, and in comments section there you said we can look up the API key to find which user it belongs to, while that can work I think it will conflict with JWT auth since its configured as a filter, and [Authorize] attributes won't work with API keys, and as well as I think looking up the DB on every request is expensive.
This was awesome, thanks Nick!
Just wondering, is there a reason for not using the IMiddleware interface when implementing the ApiKeyAuthMiddleware class?
This breaks swagger documentation.
Always great!!!!
Love your work!
Can you make a video on best ways to do data authorization? i.e. how do I make sure user x has only access to New York weather?
Brilliant, thanks!
But wouldn't that make a timing attack possible because you are just comparing the two strings without doing any hashing.
Thanks ❤
thanks
Hi Nick
Amazing video, I have a question about minimal api swagger authorize button option
How to pass different keys with the same button
I have bearer token some set of endpoint allowed with one token and other set of endpoints use another type of token.
How can we address it so Authorise button worked
Thank you
Hi Nick, that is very nice. Just a quick thought about how can I separate consumers(apps), like I want to have separate api key for each app trying to use api. Quick thought is to include app name along with key, I grab the app name and check the key. Any batter way?
Great video! thank you.
Thanks Nick. Is JWT token a good choice if I want to use dynamic key approach or there are some other better ways to do so?
You mentioned at the start about extending this to handle dynamic keys and rate limiting. How and where would you handle rate limiting per key? Love your work.
There is actually a new rate limiting feature now built into ASP .NET Core. You can use the API key as the rate limit key and it's basically done.
broooo,! so cool!
In your example, once the APIKeyMiddleware - public async Task method runs, and authentication is successful, it doesn't redirect to my Homecontroller in order to run the my Post method and continue with the request. How do I get it to direct to my post request in my Homecontroller?
I wonder is it possible the have the Authorization Filter attribute on the class level, but then override that with another Authorization Filter at the method level. That was by default the methods are safe, unless otherwise indicated.
I know you can set Filter orders but they still both get fired.
Great Video!!!!!!!!
Great!
what is the best practice for custom error to display ( custom description , custom error-code ) in minimal API despite just use 401.
So if I have an app that connects to thousands of users authentication is something I dont need, did I get that right?
is it possible to use [AllowAnonymous] annotation to bypass the middleware?
@11:20 can the Configuration not be injected here using the [FromServices] attribute on the IConfiguration contstuctor parameter? Or are Service Filters not built the same way Actions/Controllers are?
excelente video
Great video as usal, how would you go about rotating the key to thw customer, or even provide an new one securly, is there a solution already created for it?
Personnally, I would turn that `ApiKey` setting to `ApiKeys` as an array, so when you want to rotate, you add the new API key, then you replace the old one in all the places it is used and at the end, you come back and remove the old API key from your service, invalidating it.
There is actually yeah. You can use something aws secrets manage which supports rotation and versioning so both keys are supported from a single variable. I talk about that in my free aws course
@@nickchapsas guess i still havent got to this part at the course yet ... great courses both aws and the Integration tests by the way 👏🏽👏🏽👏🏽
Are you a factory that makes videos? I only now finished watching your previous one.
can you give us the book name or tutorial where did you learn this all?
Should these techniques work in the same way for Azure function triggered by HTTP or is this completely different?
Ignore that it looks like a whole minefield of complexity with Azure functions!
does this solution intentionaly do not work?
so you need to become patreon to see it works? or am I missing something.
''ApiKeyAuthMiddleware" is a type, which is not valid in the given context
is what I get
Is there a specific reason to not implement IMiddleware interface?
Nick, I purchased your zero to hero minimal API course... the discord link is broken.... is that a mistake or did you shut it down?
The Discord server is being restructured so for now no new people can join. It will be relaunched and all course owners will be notified.
Hi sir. Firstly your videos are very helpfulll for us. By the way can you give me your source code pleace...
how to use AllowAnonymous?
var actionAttributes = context.ActionDescriptor.EndpointMetadata;
if(actionAttributes.Any(x => x is AllowAnonymousAttribute))...
I was looking for the second approach, so sad 😂😂😂
First
Not a fucking clue, but very interesting
This video is difficult to understand and video editing is inconsistent with the content..
Your videos are great, but you speak too fast for non-native speakers :)
Set the playback speed in UA-cam
OMG asp net core si solo cool 🥹🥹