[HN Gopher] Oh-Auth - Abusing OAuth to take over millions of acc...
       ___________________________________________________________________
        
       Oh-Auth - Abusing OAuth to take over millions of accounts
        
       Author : skilled
       Score  : 207 points
       Date   : 2023-10-25 04:57 UTC (1 days ago)
        
 (HTM) web link (salt.security)
 (TXT) w3m dump (salt.security)
        
       | Spivak wrote:
       | What am I missing here? How do you mess this up? Like you
       | redirect to the OAuth provider with a url that has your client_id
       | and ask for a postback and you get it with a code, you use that
       | code _plus your app 's client_id/secret_ to get user-creds and
       | then query some API to figure out who just authed. The code is
       | tied to your client_id/secret. You have to implicitly verify the
       | code you got just to figure out who logged in.
        
         | michaeljx wrote:
         | An attacker could call the post back with a code generated for
         | another client_id. When you use the code to query who logged
         | in, Facebook will still respond, even if the code was not
         | generated for your client_id
        
           | rosswilson wrote:
           | This shouldn't be possible as the server-to-server request to
           | Facebook to exchange the Authorization Code for an Access
           | Token requires the client_id and client_secret to be
           | provided. Facebook should (though I haven't actually
           | confirmed this) verify that the code was issued to the given
           | client_id. If the code was issued for client 123, when client
           | 456 tries to exchange it for an Access Token Facebook should
           | throw an error.
        
         | jorams wrote:
         | What you describe is the explicit grant flow and the exchange
         | of the code for an access token automatically protects against
         | this vulnerability. The bugs here are in the implicit grant
         | flow where the redirect doesn't include an opaque code but an
         | actual access token. There the application is responsible for
         | validating that the token is for that application, but there's
         | nothing that _requires_ it to do that.
        
           | dboreham wrote:
           | I'm a little confused about this. The article seems to say
           | that the application (the server that is the target of the
           | attack) makes a call to FB where the application believes
           | that a successful response indicates that the user's
           | credentials are valid. It says that FB responds with success
           | (and the user's email). But in fact FB would respond with
           | success regardless of whether the supplied token was valid
           | (for that application). This seems like either a serious bug
           | in FB's implementation, or very bad API design. Presumably
           | it's the latter because FB is responding correctly to a
           | request that has nothing to do with auth -- application
           | (server) asked for the email for one of its users, providing
           | its (the server's) credentials for that request. The problem
           | is that the API doc/design has fooled the application
           | developer into believing that that call was an auth check.
           | But it wasn't.
           | 
           | Is that it?
           | 
           | Also...why is this not wrapped in a library such that it
           | wouldn't be possible to make such a mistake?
        
             | locallost wrote:
             | "Facebook" (or whoever) just sends a token that says the
             | user authorized the use of its account for the application.
             | What happens in this 'hack' is that the token is valid, but
             | was not actually intended for that application, but for
             | another one (e.g. a malicious one, that is now trying to
             | reuse the token to access other services of the same
             | Facebook user). I don't know how Facebook tokens look like,
             | but JWTs have a property called aud/audience indicating who
             | the token was intended for. The application developer must
             | verify that the token was actually intended for their
             | application. That is my understanding, sorry if I got it
             | wrong.
        
               | dboreham wrote:
               | I get that. You're not wrong. I'm asking _why_ Facebook
               | tells the application anything other than  "nope, that's
               | not valid for you"? It doesn't seem to be a case of the
               | application will accept random noise as a valid token. It
               | does send the token to Facebook and Facebook responds
               | with something that looks like "OK". But when they said
               | "OK" they really meant "we gave you some valid
               | information about the target user, but forgot to mention
               | that the token you provided was not valid".
               | 
               | I'm saying that Facebook should in all cases respond with
               | "Nope, that's not a valid token". Their API just
               | shouldn't have a way to get data on a user without
               | providing a valid token (by valid, we mean valid for that
               | purpose, not stolen from somewhere).
        
               | locallost wrote:
               | Because I guess in this "flow", you do not actually
               | supply the information to Facebook for them to verify
               | that claim. From the article:
               | 
               | > In steps 6-7: > randomsite.com reads the token from the
               | URL and uses it to talk directly with Facebook using the
               | following API:
               | 
               | > https://graph.facebook.com/me?fields=id,name,email&acce
               | ss_to....
               | 
               | > The response is john@gmail.com.
               | 
               | So you send the token only and the token is valid, and
               | there's no way for Facebook to check if it was meant for
               | you or not. As mentioned in other posts, this would not
               | happen in other flows because you would send e.g. your
               | client secret along with the code.
        
       | TazeTSchnitzel wrote:
       | > Vidio, an online streaming platform with 100 million monthly
       | active users, the researchers found that when logging into the
       | site through Facebook, the site did not verify the token -- which
       | the website developers and not OAuth must do. Because of this, an
       | attacker could manipulate the API calls to insert an access token
       | generated for a different application, the researchers found.
       | 
       | How does this work? I thought the token was an opaque hex string
       | and only had meaning when sent back to the original server?
        
         | vladvasiliu wrote:
         | IIRC, the user woud get an access token _from_ Facebook _for_
         | the target site, e.g. Vidio. Vidio then has to make sure that
         | not only is the token actually signed by Facebook, but also
         | that Vidio is the token 's audience. The token shouldn't be
         | opaque to Vidio.
         | 
         | I'm in no way an authority on OAuth, but I think the "opaque
         | token" you're talking about is in the situation when Vidio
         | would want to access Facebook on the user's behalf: they would
         | get an access token _for_ Facebook. The token can be opaque to
         | Vidio.
        
           | Incipient wrote:
           | Not being a full expert on it either, that flow is roughly
           | right. Vidio does have to validate it. The entire pkce flow
           | is bloody painful to implement, and it's actually quite hard
           | to do it perfectly, and easy to accidentally skip a part of
           | it and have it seemingly work ok.
        
         | tommiegannert wrote:
         | The original article [1] explains it much further:
         | 
         | > As you read previously, according to the Facebook
         | documentation, when Vidio.com receives the access token from
         | the user, Vidio should verify that the access token was
         | generated to its App ID (92356) by calling the
         | https://graph.facebook.com/debug_token API.
         | 
         | Confirming what vladvasiliu said.
         | 
         | 1. https://salt.security/blog/oh-auth-abusing-oauth-to-take-
         | ove...
        
           | arcastroe wrote:
           | Gitea serves as an OIDC provider:
           | 
           | * https://docs.gitea.com/next/development/oauth2-provider
           | 
           | However, I don't see an equivalent API in gitea to the
           | "debug_token" api.
           | 
           | If I'm developing an application that allows "Login with
           | Gitea", how do I make sure my application is not vulnerable?
        
             | vladvasiliu wrote:
             | See caseysoftware's reply:
             | https://news.ycombinator.com/item?id=38022536
             | 
             | The access token usually has an `aud` field that says for
             | whom it is.
             | 
             | I'm not familiar with Gitea's implementation, but reading
             | your link, it would seem that it acts as an oauth2 provider
             | so that 3rd parties can access _Gitea_ , not some other
             | random app.
             | 
             | > Gitea supports acting as an OAuth2 provider to _allow
             | third party applications to access its resources_ with the
             | user 's consent.
        
         | caseysoftware wrote:
         | The token _can_ be a opaque string but doesn 't have to be.
         | Often, it's a JWT which can be decoded, validated, and used
         | locally without a trip to the auth server.
         | 
         | It looks like Vidio, etc validated the signature of the JWT
         | properly but didn't check the "aud" or audience claim, which
         | defines who should use it. Therefore, it was a valid token, it
         | was for the target user, but the token itself wasn't for Vidio.
         | 
         | It's the equivalent of buying a ticket for a United Airlines
         | flight, going to the airport, and United letting you get on ANY
         | flight because you have a valid ticket.
         | 
         |  _Background: I helped build the Okta OAuth product (not
         | related to the breaches) and I 'm the author of the top
         | OAuth/OIDC course on linkedIn._
        
           | withinboredom wrote:
           | Heh, this is exactly how I got on the wrong flight once (the
           | gate changed and I didn't realize it), the machine didn't
           | tell the person I was getting on the wrong flight and the
           | attendant didn't notice.
           | 
           | The only reason I discovered I was on the flight is because
           | someone else had a ticket for my seat. The security people
           | were very curious how I did it, both pilots were very pissed
           | (both flights had to be stopped from leaving the gate until
           | they were sure I didn't leave a bag on one of the flights,
           | yay terrorism). But now you can't do that any more.
        
           | magicalhippo wrote:
           | Not just aud, but also issuer and you should check it was
           | signed by a proper certificate no?
           | 
           | https://learn.microsoft.com/en-us/entra/identity-
           | platform/ac...
        
             | vladvasiliu wrote:
             | Indeed.
             | 
             | In my case, I was initially confused by the fact that in
             | most examples (specifically for Azure AD, which is what
             | I've used), they give you an access token _for another app_
             | , here MS Graph API. It specifically says you're not
             | supposed to read that access token, so you can't validate
             | it. You should use the ID token instead (which can be
             | validated), but in the default configuration, the ID token
             | doesn't carry much information, so you need to call the
             | `userinfo` endpoint with said opaque access token.
        
               | PeeMcGee wrote:
               | For Microsoft it's another case of them going out of
               | their way to exercise every possible inch of lee-way
               | permitted by the specifications. No one in their right
               | mind should expect a userinfo endpoint to only be
               | accessible at an entirely different host. It's doubly
               | stupid that Azure AD provides no other options for remote
               | token validation, conveniently skipping the token
               | introspection extension that _every other IdP supports._
               | 
               | People writing OAuth2 clients reasonably assume that
               | trustworthy IdP's will behave normally and predictably,
               | which means Azure AD/Graph(/Entra ID?) is probably not
               | compatible with the libraries you're using. Fortunately
               | Microsoft provides their own perplexing, over-engineered
               | SDK for a handful of languages. All you have to do is rip
               | apart your existing OAuth2 plumbing and carve another
               | Microsoft-sized hole into your otherwise nice and
               | standardized application.
        
               | vladvasiliu wrote:
               | In my case, for apps that only need to authenticate users
               | with AzureAD, I've added the required information to the
               | tokens and called it a day.
               | 
               | I wouldn't bet the farm on it, but I seem to remember
               | that by default, the mozilla-oidc implementation for
               | Django was expecting an userinfo-like endpoint. And I
               | remember wasting an unbelievable amount of time trying to
               | figure how to add information to that endpoint. I've
               | never found anything, I just patched the lib to retrieve
               | the relevant fields from the tokens.
        
             | jillesvangurp wrote:
             | Depends. The core issue is that a lot of developers confuse
             | authentication and authorization. And oauth kind of muddles
             | the water on that front by vaguely doing both but not
             | really. All it does really is exchange tokens (assertions).
             | 
             | Anything JWT related is orthogonal to oauth. Oauth does not
             | actually provide any semantics for the tokens you exchange.
             | They might be JWTs and you might be able to verify them. Or
             | they might just be some random number, a hash, or some kind
             | of database id. But you would have to know in advance what
             | it is exactly and what the proper process for verifying the
             | token is.
             | 
             | In the case of a random number or some kind of session id,
             | the process of verifying that token would involve looking
             | it up from some kind of database or via some kind of API.
             | 
             | Alternatively, with a JWT, it might be a signed one
             | (hopefully) and you'd be able to check the signature if you
             | have the public key. All you have at this point is a blob
             | that was signed by someone that you might or might not
             | trust. The claims and other meta data in the token would
             | tell you hopefully who the person is (authentication) and
             | the level of access they might be given (authorization).
             | The JWT spec defines some fields that you might use for
             | that. But it's up to you to check all those things and
             | verify them.
             | 
             | The point is, that a lot of this stuff is simply
             | implementation/vendor specific and you just need to know
             | what to check and how and why. And it's on you to do all
             | those things.
             | 
             | This is not an issue with oauth, or JWTs, but with
             | incompetent developers doing things wrong or being
             | lazy/negligent/indifferent. Which sadly is very common.
             | Lots of people that get busy implementing all sorts of
             | stuff without any formal training. And a lot of this stuff
             | isn't even taught properly in schools/universities.
             | 
             | This falls in the same category as putting passwords plain
             | text in a database, not setting up ssl certificates,
             | running your database on an open port on the internet, and
             | similar things that developers do wrong all the time.
             | Because they don't even know the basics of how to do things
             | right. A lot of these things would be caught during any
             | half decent audit. And quite a few of those things could
             | expose the companies involved to some expensive law suits.
             | Which is why lots of companies spend money on audits
             | because they don't like expensive law suits.
        
               | arka2147483647 wrote:
               | Nope.
               | 
               | The thing about cryptography you always hear being said
               | is "don't roll your own crypto", because you don't know
               | all the complexities and failure modes that experts have
               | researched.
               | 
               | In o-auth, just you comment mentions multiple ways of
               | doing things, and different responsibilities the
               | developers have in different circumstances. Essentially
               | the developer is forced roll some of their own auth.
               | 
               | Compare that, for example, to say how you use TLS. You
               | just use the standard libs bundled everywhere, and open
               | connection, and the the system does all the validation
               | for you. The complexity is there, but average developer
               | is not expected to understand it.
               | 
               | O-auth simply exposes too many details to the average
               | developer, and too many options to use them differently,
               | for it to ever be secure.
        
               | robertlagrant wrote:
               | While what you say is true about OAuth2, this isn't what
               | "don't roll your own crypto" refers to, I think. It's
               | more like "don't start implementing crypto routines
               | yourself".
        
               | jillesvangurp wrote:
               | That's just the way oauth works. I agree it's a messy
               | protocol. Classic design by committee stuff. Exactly what
               | you get when mutually incompatible security product
               | vendors try to create a standard that covers what all of
               | them do.
               | 
               | Unfortunately, there are no good alternatives that don't
               | have this problem. Basically people use all sorts of
               | commercial products in the hopes that it will act like
               | magic security pixie dust. Most of them are super
               | complicated to work with. Or expensive. Or both.
               | 
               | There's just no way around the fact that you need to know
               | what you are doing and how stuff sticks together.
        
               | withinboredom wrote:
               | > incompetent developers doing things wrong or being
               | lazy/negligent/indifferent. Which sadly is very common.
               | 
               | I was code reviewing a dev who was implementing some auth
               | and I mentioned they should log something for audit
               | purposes. They said 'auditing isn't one of the
               | requirements of this ticket' ... at which point, I knew
               | it was time to leave. Like do you need someone to write a
               | ticket to do your job? When people come ask "who logged
               | in and deleted my org's content" ... you better have an
               | answer. This is software engineering 201: logging.
               | 
               | It's like an electrical engineer wiring a house not up to
               | code and saying 'I don't care because the customer didn't
               | ask for it to be up to code.'
        
               | namtab00 wrote:
               | I get what you're saying, but... Logging is not auditing,
               | AFAIK.
               | 
               | Also, and I may be very wrong based on the way that org
               | prepared tasks, he may have been signaling scope creep...
               | If it's not in the task, you don't do it. If you think it
               | should be done, you backlog it...
        
               | AckRite wrote:
               | I agree with the comment above yours but also feel that
               | this is... different style of work? Or attitude? Not sure
               | how to name it but feels like I also brushed up against
               | this numerous times.
               | 
               | I assume that line of "what is scope creep and what is
               | assumed to be in scope even if not written down" has to
               | be blurry but I tend to judge people on which side they
               | end up on, because I feel it correlates to indifference
               | etc.
               | 
               | Ultimately, it feels like a bad approach to work
               | relationships - you actually have to do personal
               | groundwork in your team to unblur the line to where you
               | and your team agrees. And if that doesn't work out -
               | leaving is a valid, if sad, option.
        
               | withinboredom wrote:
               | Not to be pedantic, but it's called an "Audit Log",
               | usually. So, it is logging, though if you don't keep your
               | logs forever, it is usually logged to a db or something
               | (but that isn't necessary -- depends on the industry,
               | privacy policy, etc.).
               | 
               | > If it's not in the task, you don't do it. If you think
               | it should be done, you backlog it...
               | 
               | You shouldn't have to be told to do your job. One day,
               | someone is going to ask why X wasn't done (when it
               | clearly should have been, by all industry standards, and
               | especially when it is exactly one line of code) and "I
               | was just following orders" doesn't work in any court,
               | including the ones that get you fired.
               | 
               | When implementing auth, almost no PM is going to write
               | down "mitigates timing attacks" as part of the acceptance
               | criteria, but you do it anyway because it is the right
               | way to do it.
        
               | pixl97 wrote:
               | And none of those things come down to the individual dev
               | in any sizable organization I've ever seen. Suddenly
               | you've started adding a db schema new db schema to the
               | requirements and are likely blowing up the sprint.
               | 
               | You push the ticker back up and fire off a few email to
               | PM and ask what the hell they are doing with the
               | requirements
        
               | withinboredom wrote:
               | Who said anything about db schemas? WTF are you talking
               | about?
        
               | phatskat wrote:
               | > he may have been signaling scope creep... If it's not
               | in the task, you don't do it. If you think it should be
               | done, you backlog it...
               | 
               | Correct. Especially if you're working for a client that's
               | billing by hour. Regardless, new work changes scope and
               | blah blah agile. Yes it's overhead, and it also creates a
               | chain of who did what, and when.
        
               | caseysoftware wrote:
               | While what you're saying applies to OAuth in general,
               | there are a lot less variables in this situation.
               | 
               | This was specifically "Sign in with.." so we know it was
               | OpenID Connect which mandates signed JWTs for ID tokens.
               | Those JWTs would have an issuer (the social provider) to
               | determine their source and the client id (to determine
               | the intended app) so those aren't in question here.
               | 
               | Further, since these are ID tokens, they WOULD provide
               | authentication information (technically identity info)
               | and minimal authorization info.
        
             | caseysoftware wrote:
             | The articles say these sites were validating the tokens -
             | as in checking signatures - so they were doing that
             | properly.
             | 
             | The issuer is another matter. Facebook or any other social
             | provider is different than using AD. With AD, every
             | customer would have a separate and distinct issuer related
             | to their specific org and config. For social auth, there
             | would be ONE issuer that everyone shares.
        
       | duttonw wrote:
       | something something jwt token for implicit flow OAuth I'd guess.
        
         | Incipient wrote:
         | Should be pkce now. I think implicit flow is entirely dead? But
         | could be wrong.
        
           | duttonw wrote:
           | it should be but auth0 was not forcing it to be off, just
           | highly suggesting to turn off that 'feature' unsure now.
        
           | duttonw wrote:
           | Another option is pkce spa, if they did not do 'auth' checks
           | that the jwt token was indeed signed by auth0 or similar, a
           | carefully crafted js alteration would let you take control of
           | the front end. Then you could give it a incorrectly signed
           | token with all the correct details for another user. Usually
           | they would only use the email for matching which makes things
           | even more trivial.
           | 
           | You would hope they verified the signing of the jwt token on
           | the backend, but seems thats too difficult for many dev's.
        
           | tansan wrote:
           | PKCE should only be necessary if you're using app linking or
           | have some client app in-between. If you completely trust the
           | server than implicit is fine.
        
             | krooj wrote:
             | No. This is wrong. Implicit is deprecated in favor of
             | authorization_code + PKCE
        
           | krooj wrote:
           | The important thing with PKCE is that it's not completely
           | secure, either. A malicious actor can create an app that uses
           | your client_id and its own code_challenge and verifier. In
           | the event that there are any issues with redirect jacking,
           | such as may be the case with custom schemes on mobile, you're
           | hosed. The only way around this is to use intents (on
           | Android) and OS pinning in the client configuration of your
           | authorization server.
        
       | geraldhh wrote:
       | finally the "login as facebook" feature everybody has been
       | waiting for
        
       | 3abiton wrote:
       | But this seems to require access to a different oauth token
       | already, ie the victim could have had their tokens from other
       | websites leaked.
        
         | usrbinbash wrote:
         | > But this seems to require access to a different oauth token
         | already
         | 
         | The article explans quite well how that works. The attacker
         | makes an outwardly legitimate service, which is registered at
         | the OAuth authentication provider, and waits for people to
         | access it. All it has to do, is store the tokens on its
         | backend, and try them, with the same username, against other
         | services, using the same auth provider.
        
       | davedx wrote:
       | Another issue with OAuth is the assumption that the browser part
       | of the flow (where the real user enters their username and
       | password on the issuer website) is actually done by a real user.
       | When I was trying to automate EV charging, I looked at quite a
       | few OAuth implementations and many of them were doing things like
       | storing the user's credentials (including their password) then
       | doing the entire OAuth flow with browser automation. I imagine
       | this was the tip of the iceberg.
       | 
       | These days with a lot of non-standards-compliant OAuth
       | implementations behind me, my conclusion is a lot of it is a
       | giant waste of time, and it often adds completely pointless
       | complexity for many of the cases it's used for. And as shown in
       | the article, all the complexity often adds exploit vectors.
       | 
       | For 90% of API use cases just issue a revokable Bearer Token and
       | be done with it. You are not an app platform!!!
       | 
       | [Qualifier: the EV API's I experimented with _were_ a good use-
       | case for OAuth, as they were user-first, based on mobile apps
       | authenticated with user /password credentials. But I've worked
       | with a lot of third party vendor API's where it was purely
       | server-to-server access, but for some reason wrapped in OAuth...
       | because... architects and compliance something something]
        
         | lathiat wrote:
         | The oaith spec requires a callback URL to work and usually that
         | url has to be "registered"/authorised with the server. Most of
         | these apps are using the api "unofficially" and the only way to
         | do that is with browser automation. Otherwise once the login is
         | complete the redirect with the authorised token won't get to
         | your app - it will go to the official website or app.
         | 
         | They then pluck the authorised token out of the cookie store.
        
           | davedx wrote:
           | Not really. The libraries should do what my own app does:
           | render the vendor website (Tesla or whoever) in a browser
           | window and let the user enter their creds securely. You can
           | then capture the auth code from the redirect just fine.
           | 
           | There are right and wrong ways to do OAuth both in server and
           | client, and many, many implementations do it wrong.
        
             | randomdata wrote:
             | _> You can then capture the auth code from the redirect
             | just fine._
             | 
             | Not when you don't have an 'official' redirect URL.
        
               | codetrotter wrote:
               | If you control the client, you can. Because when you get
               | the redirect response, you then take the auth code that
               | is included there, and you don't follow the redirect.
               | 
               | Then you send the auth code to your backend instead.
        
               | randomdata wrote:
               | Typically if you farm the job out to a browser, per the
               | discussion, then you don't have control over the client.
        
               | codetrotter wrote:
               | I took it to mean that they render the login page in a
               | web view still controlled by their app
        
               | davedx wrote:
               | Right, so my app is an electron app, and you can hook
               | into the redirect. It's still a little bit hacking the
               | flow but not as bad as full browser automation
        
             | lathiat wrote:
             | That works for GUI apps I agree though doesn't work for
             | server side stuff. Which I suspect the software the OP
             | meant is. But yes better than storing the password if you
             | are on a desktop.
        
         | Semaphor wrote:
         | > it was purely server-to-server access, but for some reason
         | wrapped in OAuth... because... architects and compliance
         | something something]
         | 
         | That sometimes feels like the bane of my existence. Everything
         | has to be OAuth and use refresh tokens, certificates etc. when
         | I never care or use any user data. No one logs in. This is all
         | our server talking to their server. Revokable Bearer Tokens
         | used to be used, but every API that updates switched to OAuth
         | which makes everything more complicated.
        
           | krooj wrote:
           | This is what the client_credentials grant flow is intended
           | for. If you're using any interactive grant flows to secure
           | S2S communications, you're doing it wrong.
        
         | figassis wrote:
         | What I hate about OAuth is how slow and cumbersome it makes the
         | process across the web. Everything requires login with google
         | for example, but that flow is so slow that it's what I dread
         | the most of all auth. Especially when I see the page reloading
         | multiple times because it wants so many other things besides
         | just auth.
        
           | PH95VuimJjqBqy wrote:
           | If you have an IAM with underlying IDP's it will legit be a
           | stack of redirects with callbacks, sometimes deeper than 1 or
           | 2. It's nuts.
        
         | caseysoftware wrote:
         | > _I 've worked with a lot of third party vendor API's where it
         | was purely server-to-server access, but for some reason wrapped
         | in OAuth... because... architects and compliance something
         | something_
         | 
         | As someone who's implemented a bunch of these..
         | 
         | It's less about compliance and more about getting everything
         | "speaking OAuth"
         | 
         | Once you've converted your user-facing flows to use OAuth and
         | you're dealing with scopes, tokens, etc, converting the backend
         | to also use it makes a lot of sense. Then you have ONE path for
         | token validation, inspecting/validating scopes, and client
         | id/secret issuance whether you're on the front or back end.
         | Having one model for people to understand makes things tangibly
         | simpler and shrinks the libraries/tools you need.
         | 
         | If you ONLY have backend (service to service) flows with a
         | simple authZ model, OAuth is usually overkill.
        
           | PH95VuimJjqBqy wrote:
           | OAuth is usually overkill, period.
           | 
           | There are only two real use cases for the complexity of
           | OAuth.
           | 
           | 1. SAAS model and you're allowing your customers to use their
           | own IDP
           | 
           | 2. You really and truly have a lot of disparate internal
           | systems that need SSO.
           | 
           | And 2 generally has better solutions.
        
             | sleepybrett wrote:
             | > And 2 generally has better solutions.
             | 
             | you fail to mention them.
        
               | PH95VuimJjqBqy wrote:
               | because it depends on the specific needs. It could be as
               | simple as LDAP integration or as complex as OAuth.
        
               | marcosdumay wrote:
               | One really shitty thing is that people keep inventing
               | those badly-though protocols like OAuth, and yet nobody
               | (as in no browser) ever implemented LDAP over the web.
        
               | pixl97 wrote:
               | Isn't ldap in the browser just something like NTLM?
        
               | marcosdumay wrote:
               | Negotiate uses the OS LDAP tokens on the web.
               | 
               | Windows has that stupid rule where LDAP runs all over the
               | OS or nowhere at all, and Linux has that idea that LDAP
               | is some add-on you assemble by connecting a jigsaw of
               | pieces. Nothing makes it reasonable to publish a domain
               | on the web, where people can authenticate on many of
               | them, and send the tokens where needed.
               | 
               | (Well, actually Firefox does most of it, and you can use
               | it and assemble the Linux pieces so it works. It just
               | doesn't work in practice.)
        
               | Spivak wrote:
               | Look I'll sing LDAP's praises when it's appropriate but
               | this really isn't it. It's less of SSO and more "Same
               | Password Everywhere" which are not at all the same
               | experience from the user perspective. It also teaches
               | your users to plug their creds into random login screens
               | instead of the one-true-login-page they can verify is us.
               | 
               | Like as hackers we make fun of the phishing training that
               | teaches you to avoid sketchy links in emails while
               | simultaneously the real emails have the sketchiest links
               | of all time. Using LDAP for this use-case is our version
               | of that.
        
               | caseysoftware wrote:
               | ^ This.
               | 
               | We should teach users to put their passwords into very
               | few, limited, and trusted places. The cool new social app
               | is NOT trusted. That random app on your phone is NOT
               | trusted.
               | 
               | There's even an xkcd on this one: https://xkcd.com/792/
        
               | pmontra wrote:
               | That xkcd is about the downside of using the dame
               | password on many services. No service is really trusted
               | so what we should teach people to do is, as usual, to use
               | a password manager to randomly generate a new password
               | for every service. Maybe that's what you were advocating
               | but it was not clear to me.
               | 
               | We should also teach to ourselves to throw away all those
               | weird rules about passwords, like 6 to 15 characters max,
               | letters and digits and a random set of punctuation
               | characters liked by the site owner. Why those limits when
               | they are storing a hash anyway?
        
               | PH95VuimJjqBqy wrote:
               | name something that doesn't have downsides.
               | 
               | go on, I'll wait.
        
               | iimblack wrote:
               | Yikes ignoring that there can be different severity and
               | type of downside
        
               | PH95VuimJjqBqy wrote:
               | somehow "depends on the specific needs." got turned into
               | "ignoring different severity and downsides".
               | 
               | Who knows what goes through people's heads.
        
               | sleepybrett wrote:
               | Well lets talk about your average 'bigcorp'. You've got
               | laptops you need to log into, you've got network shares
               | you need to log into, you've got internal web
               | applications you need to log into, you've got external
               | saas bullshit you need to log into, you have some cloud
               | accounts you need to access... You need to manage this
               | for thousands of people, probably 10s of thousands of
               | people.
               | 
               | You don't want your average user to have a great many
               | usernames and passwords, maybe two or three at most to
               | manage. You also probably don't want to have them share
               | those credentials.. though without 'one big system' you
               | can't really prevent that. You also probably want some
               | kind of system with 2factor support through a few
               | different methods, rolling code, sms, yubikey, etc.
               | 
               | LDAP ain't it.
               | 
               | From where I set Oauth seems to be the current solution
               | with the least number of downsides. It's complicated for
               | sure, the flows are easy to fuck up, but I haven't seen a
               | better solution.
               | 
               | Maybe Passkey is it, i keep meaning to read the rundown
               | but I just haven't found the time... and also it's
               | realativly new enough that support and open source
               | solutions might be a little sparse...
        
               | PH95VuimJjqBqy wrote:
               | To hear you describe it, SSO didn't exist before OAuth.
               | 
               | And yet it did.
        
         | marcosdumay wrote:
         | > because... architects and compliance something something
         | 
         | At work the tooling we use for our services outright requires
         | OAuth if you want authentication. And yeah, that's a large
         | factor implying we should use something else, but there are
         | many coordination problems for that.
         | 
         | I imagine plenty of people have a similar problem.
         | 
         | Anyway, if your client is saving your password, then I'd say
         | that's not a good use-case for OAuth. At this point I'm not
         | sure there exist a good use-case for OAuth.
        
         | judge2020 wrote:
         | Tesla only just recently opened the ability to be an official
         | oauth application, so all apps before now either required
         | storing username+password or the long-lived token it sends back
         | once you authenticate.
        
       | mgaunard wrote:
       | Or you can just use JWT which instead of asking the identity
       | provider whether a token is valid simply requires you to check
       | its signature against a public key.
        
         | camkego wrote:
         | Some of the vulnerabilities in the article are due to
         | validating the signature of the JWT properly but not checking
         | the "aud" or audience claim. Honestly, I would be tempted to
         | call back to check the token due to how easy it is to make a
         | mistake with JWT.
        
           | mgaunard wrote:
           | Of course, it just checks that the token was indeed generated
           | by the identity provider. You still need to check that its
           | contents match what you expect for your application.
           | 
           | Issuing a request to another server from my backend would be
           | a non-starter, completely incompatible with any sensible
           | performance or security model.
        
             | mooreds wrote:
             | > it just checks that the token was indeed generated by the
             | identity provider.
             | 
             | This! I have given a talk on JWTs dozens of times and
             | always emphasize that you must do two things:
             | 
             | * verify the signature
             | 
             | * validate the claims (including standard ones like `aud`
             | and non-standard, business specific ones)
             | 
             | You must must must do both to securely trust the token.
             | 
             | This isn't just a JWT thing, either. If you provide a token
             | to an introspect endpoint like what Facebook provides, only
             | the first item is taken care of. You must still inspect the
             | claims.
             | 
             | Libraries will sometimes help with the standard claims, but
             | you're on your own for non-standard ones.
        
       | 29athrowaway wrote:
       | tl;dr: it was an open redirect.
        
         | talkin wrote:
         | No, it wasn't.
         | 
         | It's not validating reused codes or tokens from an application
         | owned by attacker.
        
           | 29athrowaway wrote:
           | True, thanks for noticing. I re-read it more carefully
        
       | bjt12345 wrote:
       | .
        
       | raselhanout wrote:
       | > OAuth also uses an "explicit grant type," which is similar to
       | "implicit grant type" but the server (randomsite.com) receives a
       | code instead of a token and needs to make an additional request
       | to Facebook to exchange it for a token. We're using the implicit
       | grant type example here because it is easier to understand and
       | relevant to this post.
       | 
       | Are the first two attacks possible with explicit grant ? Wouldn't
       | the auth server return an error if the client tried to request
       | the access token with their secret and the code from another
       | client ?
        
         | sigwinch28 wrote:
         | No, they're not possible. Yes, the auth server would return an
         | error because the token is retrieved by the server out-of-band
         | (Mallory can't intercept via the browser) and must provide its
         | credentials to Facebook to retrieve said token.
         | 
         | Additionally, Facebook SHOULD check that the client using the
         | code is the same client that initiated the OAuth flow.
        
       | agentultra wrote:
       | Securing an OAuth implementation is hard. There've been several
       | appendices added to the spec that many developers are probably
       | not aware of [0]. Remember to check for current best practices to
       | learn about the latest mitigations and protocol updates!
       | 
       | [0] https://www.ietf.org/id/draft-ietf-oauth-security-
       | topics-24....
        
       | vinckr wrote:
       | You probably dont need OAuth2/OIDC. While the two are very
       | powerful protocols when used correctly, and have many advantages
       | and use cases, the truth is that they are not always necessary.
       | In fact, you most likely do not need them.
       | 
       | - https://www.ory.sh/oauth2-openid-connect-do-you-need-use-cas...
        
         | kriops wrote:
         | I don't disagree, but I want to expand upon your point in a
         | cautionary direction: Using OIDC/OAuth2 does prevent you from
         | making several classes of rudimentary mistakes, entirely for
         | free. The nonces and whitelists aren't there just to look
         | pretty!
        
       | fastest963 wrote:
       | You can send appsecret_proof instead to validate the token and
       | the app. See https://developers.facebook.com/docs/facebook-
       | login/security...
        
       | nstart wrote:
       | Hang on... So this means that when I check the token as per the
       | guide at https://developers.facebook.com/docs/facebook-
       | login/guides/a... , it returns the information regardless of the
       | access_token parameter matching the app id or not? My assumption
       | without reading the docs would have been that if the input_token
       | was from another app, FB would refuse to debug it if the
       | access_token was not associated with the app id.
       | 
       | What's the point in asking for the access_token at all for that
       | endpoint otherwise?
       | 
       | Am I misunderstanding the bug? This feels like a foot gun that
       | was happily handed over to a lot of people all this time.
        
       | wunderwuzzi23 wrote:
       | Don't forget about ROPC!!
       | 
       | There is also an MFA bypass that I see often, it's the Resource
       | Owner Password Credentials (ROPC) flow in OAuth.
       | 
       | Especially when you have an Microsoft M365/Azure tenant. Pretty
       | much every client that I have ever tested had this issue. When
       | ROPC is configured (which is the default) then you can just use a
       | simple password to logon (and it bypasses MFA).
       | 
       | More details and a tool to test your own tenant:
       | https://embracethered.com/blog/posts/2022/ropci-so-you-think...
       | 
       | If you use M365/Azure test and see if you can logon without MFA,
       | you might be surprised.
        
       | charles_f wrote:
       | > the OAuth protocol itself is indeed correctly designed and is
       | secure by nature. However, to use it with a web service requires
       | integrating it into that service's existing platform, which is
       | where the trouble starts
       | 
       | That's my main beef with OAuth. I like having a standard in the
       | middle, I also like OAuth, and I think I understand some of the
       | flows well (I have enough knowledge to know I'm not an expert).
       | 
       | The main issue is that it is complex enough that you can botch
       | the implementation in multiple places (eg misuse of the
       | refresg_token), flexible enough that you can take the wrong
       | shortcuts (eg use the wrong flow), and most implementations have
       | semi-transparent intermediary points (eg Jwt that you can see
       | into) that make you feel like you understand the whole thing
       | while you only get half of it - or once again use a component for
       | something it should not be used (id_token for authorization being
       | the most common).
       | 
       | It's better than inventing your own scheme, which is certain to
       | fail. But most people don't spend or don't get the time they need
       | to understand properly. It doesn't result in gaps necessarily,
       | but it can.
        
         | candiddevmike wrote:
         | You can use your existing API tokens as the OAuth access_token.
         | Refresh tokens are optional. None of it has to be a JWT. Doing
         | this prevents having to support multiple API auth methods.
         | 
         | OIDC on the other hand...
        
           | charles_f wrote:
           | That's precisely the point. You _can_ do those things, or you
           | can _not_ do them. And there are paths in the combinatorial
           | that leave you with an open door.
           | 
           | Re: OIDC, that's yet another one. The average dev can't tell
           | you the difference between both - or won't even know the term
           | OIDC and call it OAuth.
        
       | foxyv wrote:
       | I recently implemented some code to: Sign into an account using
       | username/password/MFA, authenticate with an API using OAuth to
       | get a SAML assertion, authenticate with another API using the
       | SAML assertion to get a token, then sign into an API using the
       | token...
       | 
       | Why do we do this to ourselves?
        
         | jeroenhd wrote:
         | Not having to deal with auth yourself makes your life so much
         | easier.
         | 
         | For my self hosted stuff, I've out a simple OIDC requirement in
         | my Apache config (https://github.com/OpenIDC/mod_auth_openidc)
         | and have set up a plain Keycloak server (should've gone with
         | something simpler but oh well). Apache now sets the user ID in
         | a header (that doesn't get passed on from the client for
         | obvious security reasons) and all the application on the other
         | end needs to do is look up the user ID. Multi factor
         | authentication, password recovery, session expiration and
         | everything else is all handled by Keycloak and no
         | unauthenticated requests can make it through Apache. Tokens are
         | signed and verified, of course, so there's no faking anything.
         | 
         | I think Caddy has a similar system built in, including a login
         | page and everything. Give or six lines of config are all you
         | need to handle authentication, plus you get automatic security
         | updates for your authentication flow in case something happens.
         | 
         | There's a reason Okta and its competitors are selling auth as a
         | service: doing auth yourself properly is a massive pain that
         | you need to stay on top of. You need to set up secure hashes,
         | integrate TOTP/FIDO2 with appropriate recovery mechanisms, set
         | up login flows, deal with session expiration, and all that
         | stuff, when all you want is "give me a user ID so I know what
         | data to load".
         | 
         | These systems are annoying to develop against (though plenty of
         | libraries are available to do the hard parts for you) but
         | they're great if you just want to secure a backend or web
         | application.
         | 
         | I don't know why you needed two extra assertions when you were
         | already authenticated, though. That's sounds like bad
         | integration to me.
        
           | foxyv wrote:
           | Signing into AWS API through OKTA using a SAML Identity
           | Provider. Just the way it was implemented unfortunately.
           | OKTA's API is okay for this sort of stuff, but they need a
           | SAML Assertion API that doesn't require scraping HTML. Also
           | it would be nice if their JSON formatting weren't so all over
           | the place.
           | 
           | So it went: OKTA Assertion -> OKTA SAML Assertion -> AWS STS
           | Token
           | 
           | > That's sounds like bad integration to me.
           | 
           | No arguments here.
        
       | fulafel wrote:
       | Are these cases all implicit flow, except the Grammarly case
       | where a bug/misconfiguration made it accept the implicit flow
       | param anyway?
        
       | Foobar8568 wrote:
       | I read a lot of things in oauth, implemented several Saas/API
       | access for server to server communication, and I feel it's so
       | insecure that I am sure I have missed something...
        
       | krooj wrote:
       | This article is not as impressive as one might imagine - the
       | exploit appears to use the implicit grant flow, which is
       | officially deprecated and should be replaced by the
       | authorization_code + PKCE flow.
        
       | gerardnico wrote:
       | It should not happen if you have a proper state that is local,
       | unknown from the attacker and temporarily valid.
       | 
       | https://datacadamia.com/iam/oauth/state
        
       | woranl wrote:
       | Which version of OAuth implementation is at risk? 2.0 and 1.0a
       | are quite different.
        
       ___________________________________________________________________
       (page generated 2023-10-26 23:02 UTC)