I currently create JwtSecurityToken and return the token to the user after request to /account/login. I use jwt bearer middleware that handles token verification upon each request. Everything works fine. I don't use OpenID Connect nor OAuth2.
Does it also mean I use my own protocol?
Now, what would be the advantage over this approach if I used OpenID Connect (through IdentityServer or OpenIddict)?
I'm still new to these protocols and I'm only familiar with JWT (format) itself.
From my basic understanding OAuth2 or OpenID Connect is used when I want to expose my API to third parties, but what if I need to secure my private API and I don't want anything else except my programs (native,mobile,web) to have access to it. Would those protocols still help?
I was reading one advantage is Single sign-on (SSO) but if JWT itself can be shared across domains etc. wouldn't it mean I can achieve the same without OpenID?
Please note that I know JWT is format and OpenID Connect is extended OAuth2 protocol standard that use JWT. And IdentityServer, OpenIddict are implementations of these protocols.
So, can I summarise what you're doing to see if I understand it?
What are you actually wanting to do? You can use OIDC to authenticate and then use the issued tokens for access a private API, that's fine. The advantage of that is you don't end up writing custom code for issuance, and you could use the same flow if you decide to write a mobile app, for instance. But you don't have to go that route, just like you don't have to use JWT, it's just standard formats and standard flows tend to have a lot of support in frameworks, so you can avoid spending time reinventing them.
@blowdart Yes you're correct. In the simplest my authentication looks like that now:

I issue tokens using JwtSecurityToken, basically something like that: https://jonhilton.net/2017/10/11/secure-your-asp.net-core-2.0-api-part-1---issuing-a-jwt/
I don't want consent screen or anything like that, that is most often used if I want it to be used by a third party as I want to use the API in the native desktop apps and mobile apps too and I want the auth to happen in the background (transparently)
Will using OIDC (standard flow) save me time writing client-side logic for dealing with authentication? Is it a good fit if I'm planning to use the API internally only? How will my authentication logic look on the server then? Will I still have to provide my own login endpoint that issues tokens? Like /account/login but instead of creating token there, calling OIDC endpoints?
So this veers into opinion now, so in _my opinion_
Yes, it will save you a bunch of time writing client side code, but that's offset by the time taken to implement the server side pieces needed via OpenIddict or Identity Server, which would become your login endpoint.
Your auth logic wouldn't change.
Essentially, you're implementing your own ROPC-like flow (ROPC = resource owner password credentials), which is the simplest OAuth2 flow (but also the only one not suitable for third-party client authorization). I say "ROPC-like" because it doesn't use standard-compliant parameters and doesn't take things like client authentication into account.
Whether you go with your custom thing or with an OIDC server that will do it for you, the client part will be roughly the same, as it only consists in sending a HTTP request with the username/password and extracting the access token from the response in both cases.
Yes, it will save you a bunch of time writing client side code, but that's offset by the time taken to implement the server side pieces needed via OpenIddict or Identity Server, which would become your login endpoint.
Well, implementing the ROPC flow is super easy and only requires a few lines of code (at least, with OpenIddict): http://kevinchalet.com/2017/01/30/implementing-simple-token-authentication-in-aspnet-core-with-openiddict/
If you're afraid of OpenIddict and IdSrv being "too heavy" for your scenario, here's the equivalent of what's done in the blog post using ASOS, the OIDC server handler being OpenIddict, which can be done in a totally stateless way (i.e with no backing DB):
private static readonly SecurityKey Key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes("your HMAC key, hopefully generated using a crypto-secure RNG"));
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication()
.AddOpenIdConnectServer(options =>
{
options.TokenEndpointPath = "/token";
options.AllowInsecureHttp = true;
options.SigningCredentials.AddKey(Key);
options.AccessTokenHandler = new JwtSecurityTokenHandler
{
OutboundClaimTypeMap = new Dictionary<string, string>()
};
options.Provider.OnValidateTokenRequest = context =>
{
if (!context.Request.IsPasswordGrantType())
{
context.Reject(OpenIdConnectConstants.Errors.UnsupportedGrantType);
}
else
{
// Don't enforce client authentication.
context.Skip();
}
return Task.CompletedTask;
};
options.Provider.OnHandleTokenRequest = context =>
{
// Implement context.Request.Username/context.Request.Password validation here.
// Using password derivation and time-constant comparer is STRONGLY recommended.
if (context.Request.Username == "bob" && context.Request.Password == "bob")
{
var identity = new ClaimsIdentity(context.Scheme.Name);
identity.AddClaim(new Claim(OpenIdConnectConstants.Claims.Subject, "Bob"));
var ticket = new AuthenticationTicket(
new ClaimsPrincipal(identity),
new AuthenticationProperties(), context.Scheme.Name);
ticket.SetResources("resource_server");
context.Validate(ticket);
}
else
{
context.Reject(OpenIdConnectConstants.Errors.InvalidGrant);
}
return Task.CompletedTask;
};
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters.ValidAudience = "resource_server";
options.TokenValidationParameters.ValidIssuer = "http://localhost:54540/";
options.TokenValidationParameters.IssuerSigningKey = Key;
});
services.AddMvc();
}
@Necronux What is your conclusion?
Have you implemented OpenIddict or Identity Server?
I have a similar application, I only have authentication for SPA and Mobile
@marcrib I still generate JWT tokens myself(I have only 1 type of token that is access token, no refresh tokens), I only have one desktop application now that needs to communicate with the API. I didn't see any reason to use OpenIddict/IdentityServer. My API is used only internally (not by third parties). Nobody can really precise why should you use OpenIddict or identity server especially when all you need is just a simple auth for your private API.
I think you should ask yourself what problems do you try to solve using OpenID Connect and how will it be better than issuing it yourself.
Just like @PinpointTownes mentioned it is pretty much like ROPC( resource owner password credentials) flow in OAuth. So I think if you only need this, and don't need other grant types/flows it shouldn't make any difference except different standardized requests and responses (and endpoints).
JWT is just a token format, it's main purpose is to share claims or pieces of information about a user.
OID uses JWT too, but it defines flows(ways of obtaining the tokens) for a different set of problems when you don't really want to authenticate with username and password. It also gives you more types of tokens other than access token, like id token and refresh token. (see https://stackoverflow.com/questions/39438363/jwt-why-do-i-need-a-refresh-token and https://stackoverflow.com/questions/3487991/why-does-oauth-v2-have-both-access-and-refresh-tokens )
Also, https://stackoverflow.com/questions/39909419/jwt-vs-oauth-authentication more or less explains the difference.
I think @PinpointTownes knows best when to use what so I think you might get the better explanation from him.
Should you really use standard if you're the only person accessing that API from your app? I don't know. I think the standard was created mainly to solve the problem with exposing the API to third parties, and to define some set of rules to make it more secure... but it has this ROPC flow so I think it can serve multiple purposes (i.e. third party and first party)
Personally, I think the standard is not well defined and many people get confused whether they should use it or not: https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529 Many people use them because they're told to do so (like sheeps).

There also is a problem many people praising tokens neglect to mention: invalidating the tokens. In practical applications you mostly need some button like "logout" and solution for this is not well defined (primarily opinion based) and mostly involves storing these tokens in some database, many people recommend redis for this but it can be stored anywhere.
In my opinion, every library and every standard should give some clear list of problems it tries to solve with real-life examples, instead of giving just tutorials etc. for blindly using it.
Also worth adding:
Official website of OAuth states that OAuth2 is not authentication protocol https://oauth.net/articles/authentication/
An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications.
There's a lot of confusion about this on the internet and using OAuth2 for authentication is referred to as "pseudo-authentication" and officially it's misusing it.
@Necronux thanks
check https://github.com/aspnet/Announcements/issues/307
"Authorization Server"
We periodically close 'discussion' issues that have not been updated in a long period of time.
We apologize if this causes any inconvenience. We ask that if you are still encountering an issue, please log a new issue with updated information and we will investigate.
Most helpful comment
Essentially, you're implementing your own ROPC-like flow (ROPC = resource owner password credentials), which is the simplest OAuth2 flow (but also the only one not suitable for third-party client authorization). I say "ROPC-like" because it doesn't use standard-compliant parameters and doesn't take things like client authentication into account.
Whether you go with your custom thing or with an OIDC server that will do it for you, the client part will be roughly the same, as it only consists in sending a HTTP request with the username/password and extracting the access token from the response in both cases.
Well, implementing the ROPC flow is super easy and only requires a few lines of code (at least, with OpenIddict): http://kevinchalet.com/2017/01/30/implementing-simple-token-authentication-in-aspnet-core-with-openiddict/
If you're afraid of OpenIddict and IdSrv being "too heavy" for your scenario, here's the equivalent of what's done in the blog post using ASOS, the OIDC server handler being OpenIddict, which can be done in a totally stateless way (i.e with no backing DB):