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

Steam OpenID & JWTs #50

Closed
jacobmstein opened this issue Nov 18, 2018 · 24 comments
Closed

Steam OpenID & JWTs #50

jacobmstein opened this issue Nov 18, 2018 · 24 comments

Comments

@jacobmstein
Copy link

@jacobmstein jacobmstein commented Nov 18, 2018

When using the default JWT middleware instead of cookies I get An unhandled exception occurred while processing the request. The authentication handler registered for scheme 'Bearer' is 'JwtBearerHandler' which cannot be used for SignInAsync.

From ConfigureServices:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateAudience = true,
            ValidateIssuer = true,
            ValidateIssuerSigningKey = true,
            ValidateLifetime = true,
            ValidAudience = Configuration["Jwt:Issuer"],
            ValidIssuer = Configuration["Jwt:Issuer"],
            IssuerSigningKey = new 
            SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
         };
     })
     .AddSteam(options =>
     {
         options.CallbackPath = "/verify";
     });

Is there any way to override the /verify callback, manually call the library to authenticate the user, then issue a JWT afterwards? My understanding is SignInAsync is being called automatically.

TL;DR: Can I override the verification callback and incorporate it into my own logic, e.g. verify the user and return a value?

Thanks,
Jacob

@jacobmstein jacobmstein changed the title How can I use this to issue JWTs? Steam OpenID & JWTs Nov 18, 2018
@vlapoec

This comment has been minimized.

Copy link

@vlapoec vlapoec commented Feb 6, 2019

Did you find a way to resolve this issue ?

@jacobmstein

This comment has been minimized.

Copy link
Author

@jacobmstein jacobmstein commented Feb 6, 2019

Unfortunately not, I ended up switching to Node for better control over the call back.

@kevinchalet

This comment has been minimized.

Copy link
Member

@kevinchalet kevinchalet commented Feb 6, 2019

The JWT middleware can't be used for issuing JWT tokens: its only mission is to validate them, which is why you get an exception when trying to use it as the DefaultSignInScheme.

The scenario you describe is usually achieved by adding an OpenID Connect server (OIDC):

Client (e.g a SPA or a mobile app) -> your OIDC server embedded in your ASP.NET Core app -> Steam (OpenID 2.0 dance) -> your OIDC server -> client.

Projects like IdentityServer (developed by Thinktecture) or OpenIddict (that I develop and maintain) can help you with that.

@vlapoec

This comment has been minimized.

Copy link

@vlapoec vlapoec commented Feb 6, 2019

Thanks a lot @PinpointTownes

That sounds exactly like what I need but I don't really understand.

If I'm hosting an IdentityServer, I'm the one who authenticates my users. Will they still be able to log into my website with their steam accounts ? And I will be able to identify their steam info ?

@kinosang

This comment has been minimized.

Copy link
Contributor

@kinosang kinosang commented Feb 6, 2019

@vlapoec IdentityServer or other OpenID Connect servers (ASOS, OpenIddict, and etc) are works well with 3rd party login, such as OAuth and OpenID.

Please refer to Asp.Net Core Identity docs and IdentityServer docs for more information.

Simply you can just add services.AddAuthentication().AddSteam() and app.UseAuthentication() (for IdentityServer it's replaced by app.UseIdentityServer())

@vlapoec

This comment has been minimized.

Copy link

@vlapoec vlapoec commented Feb 6, 2019

Thank you I will dig into that

@verdie-g

This comment has been minimized.

Copy link

@verdie-g verdie-g commented Feb 16, 2020

I have found another solution which is handling the redirection yourself in SteamAuthenticationOptions.Events.OnTicketReceived and passing the jwt in a query parameter. See https://stackoverflow.com/questions/59734317/return-a-jwt-after-authenticating-via-open-id.

@kevinchalet

This comment has been minimized.

Copy link
Member

@kevinchalet kevinchalet commented Feb 16, 2020

@verdie-g looks like a super dangerous solution: your RedirectUri endpoint accepts a token parameter in the query string without any additional anti-forgery validation.

The lack of CSRF countermeasures in a callback endpoint typically results in a session fixation vulnerability: nothing prevents a bad guy from authenticating with his own account, extracting the JWT associated to his account and forging a URL he'll be able to send to a victim, that will be logged in as the attacker once clicking on the link.

There's really a reason if we suggest opting for battle-tested options: these threats are clearly identified in standard protocols.

@verdie-g

This comment has been minimized.

Copy link

@verdie-g verdie-g commented Feb 16, 2020

Indeed, in my case I'm forbidding CORS which I think, mitigates this security issue (?). Anyway, I should dig more into OIDC servers but it feels so overkill for the size of my project.

@kevinchalet

This comment has been minimized.

Copy link
Member

@kevinchalet kevinchalet commented Feb 16, 2020

Indeed, in my case I'm forbidding CORS which I think, mitigates this security issue (?).

Nope, neither the same-origin policy nor same-site cookies will mitigate that, as the victim directly visits the vulnerable callback endpoint in the attack I described.

@verdie-g

This comment has been minimized.

Copy link

@verdie-g verdie-g commented Feb 16, 2020

I misread your scenario. In my case, you have nothing to gain by allowing someone else to log in your account. But my solution is really dirty anyway.

@kevinchalet

This comment has been minimized.

Copy link
Member

@kevinchalet kevinchalet commented Feb 16, 2020

In my case, you have nothing to gain by allowing someone else to log in your account.

Information theft is the main risk with this attack: if your website allows the user to send personal data, you're at risk, as the data will be attached to the attacker's account.

@verdie-g

This comment has been minimized.

Copy link

@verdie-g verdie-g commented Feb 16, 2020

I understand. Thanks for pointing this issue.

@kevinchalet

This comment has been minimized.

Copy link
Member

@kevinchalet kevinchalet commented Feb 16, 2020

To be honest, it's not the first time I hear someone trying to implement a custom protocol instead of using a battle-tested standard like OIDC (and well-known implementations like IdSrv or OpenIddict).

I'm considering writing a blog post introducing OpenIddict 3.0's degraded mode, which allows using OpenIddict's server without any database. It's a perfect use case for a tiny proxy between a single client and a remote identity provider (Steam in this case). Would you be interested?

@verdie-g

This comment has been minimized.

Copy link

@verdie-g verdie-g commented Feb 16, 2020

I would be very interested! I have started reading OpenIddict doc which is way more clearer than IdentityServer's one, no magic everywhere. But if I have implemented my custom protocol it is mostly by pure laziness because I didn't find the article matching my use case.

@vlapoec

This comment has been minimized.

Copy link

@vlapoec vlapoec commented Feb 16, 2020

@kevinchalet

This comment has been minimized.

@verdie-g

This comment has been minimized.

Copy link

@verdie-g verdie-g commented Feb 18, 2020

That was fast thanks! I'll read that as soon as a I can.

@kevinchalet

This comment has been minimized.

Copy link
Member

@kevinchalet kevinchalet commented Feb 18, 2020

@verdie-g my pleasure 😄

@kevinchalet

This comment has been minimized.

Copy link
Member

@kevinchalet kevinchalet commented Feb 22, 2020

Closing, as I believe my blog post answered the original question. If not, please add a comment and I'll give it a look.

@Gameghostify

This comment has been minimized.

Copy link

@Gameghostify Gameghostify commented Feb 28, 2020

The Cookie authentication scheme here works without having to add something as heavy as asp net core identity or even identity server to your project

On that note: Does that mean we could create a custom auth scheme that implements SignInAsync?

@Gameghostify

This comment has been minimized.

Copy link

@Gameghostify Gameghostify commented Feb 28, 2020

I'd love to use steam authentication but keep using my own user system, without having to switch to one given by ASP.NET Core Identity/IdentityServer or implementing something like OpenIddict

@kevinchalet

This comment has been minimized.

Copy link
Member

@kevinchalet kevinchalet commented Feb 28, 2020

@Gameghostify nothing prevents you from doing that. As you figured out, you can use the cookies authentication handler alone and build your own membership mechanism on top of that.

@Gameghostify

This comment has been minimized.

Copy link

@Gameghostify Gameghostify commented Feb 28, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
6 participants
You can’t perform that action at this time.