1
9 Comments

Auth Secret isn't a secret key!

In Authentication Standards like OAuth 2.0, we use client id and secret for authenticating machines. When we authenticate a client in a system, we find that for example, it is application X on the android or application Y web version.

But why we have a key named "secret"? it isn't a secret key at all on all clients except servers. You can extract it easily from a web application code or mobile application traffic (even if it is on https).

Am I wrong or is this mean another thing than a secret key that only the owner or that key knows (like user password)?

on June 1, 2020
  1. 2

    The idea is that you don't expose the secret key anywhere in public. Usually, the secret is only used between your servers and OAuth tenant and never shown in the browser: https://auth0.com/docs/flows/concepts/auth-code. The security achieved by enforcing https and verifying URL code. Some services also have a signature for payload.

    There are OAuth implementations of client-side flow (with no server involved) but they usually don't have secret keys (you're right those can be stolen) and nothing coming from the client in that flow should be trusted. For example, Firestore (from Firebase) has security rules enforced on the backend to enable client-side only auth.

    If you have a specific flow you want to discuss, please post it here and we can go into more detail.

    1. 1

      Thanks for the description, but I'm a bit confused.
      The main question is:
      Imagine you generated a client id and secret to access an API from a web client.
      Then I steal them and make requests instead of your web application.
      Even if you store your id and secret server-side, you have to make a secure request to your server and it's not possible because your web app's request is public from every browser.
      So is my client id and secret for myself yet?

      1. 2

        I believe the client_secret is for authorisation (i.e. is this app allowed to make this kind of request). Stealing the client_secret would still require hacker to authenticate (to make request on behalf of a specific user). But yes it seems weak.
        https://salesforce.stackexchange.com/questions/14009/whats-the-benefit-of-the-client-secret-in-oauth2

        1. 1

          I know that client credentials are for authorizing a client, not a user and there are no real security problems with stealing them. I'm talking about evaluating real data about one client's requests!

          1. 2

            Ah OK. Get you now. Seems you are right and the recommendation today is to not use OAuth client secret in client apps because of the problem you describe.

            Have you seen these:

            1. https://oauth.net/2/pkce/
            2. https://tools.ietf.org/html/draft-parecki-oauth-browser-based-apps-02
            3. https://tools.ietf.org/html/draft-ietf-oauth-security-topics-15

            Section 6 of #2 suggests exhausting these options first:

            1. Don't use OAuth.
            2. Use in backend.
            1. 1

              Thanks for the links. I know about PKCE (Pixie)
              But I'll read 2 next links later!

      2. 2

        Let's go over a typical oAuth back-end flow, the one you'll probably use 80% of the time:

        1. You have a web client and your backend server which has your oAuth client and secret.
        2. Your user goes to a specific endpoint on your back-end, let's say yourdomain.com/oauth.
        3. Your Server gets that request and redirects browser to the oAuth page using your client_id. The customer (or any attacker) will see your client_id and this is fine. That URL must have a redirect_url that page will be redirected once a user enters credentials.
        4. After a user is successfully authorized page is redirected to the endpoint from step 3 with a short-living auth code (usually 5 to 10 minutes).
        5. Your Server gets this code from URL params and sends the request to oAuth provider to obtain Access and Refresh token. This request will require your secret, but that request will be invisible to any user or attacker as it happens in the backend. Https is enforced for this flow, so the only way for attacker to interject is to be able to fake certificates and somehow execute man-in-the-middle attack. While possible, it is super inefficient, since you can invalidate ALL tokens issued for your client_id in a few clicks, so an attacker will gain a very limited amount of data.
        6. Your Access token is the one you use to request API on behalf of the user. It is also short living and usually only valid for an hour.
        7. Refresh token is used to get new access tokens. Depends on implementation, you usually will use the same refresh token for about half a year. Some APIs allow you to get a new refresh token without user, some will send you refresh tokens with access tokens, some will not bother at all. Refresh tokens should also be kept secure and not exposed easily.
        8. If you ever suspect a leak of any information above, you just go and invalidate all the tokens, generate a new pair of secret/client_id and make your users reauthorize again. Even in case of a data breach, you don't leak any private information of users. And even if attackers stole your access tokens (they are sent over https and technically can be stolen, e.g. on a public wifi) it will only give them access for a maximum of half an hour.

        Let me know if this makes sense,
        Sergey

        1. 1

          Thanks for the time you invest in this question. I'm not talking about stealing data by an attacker. I told you that I can use your client credentials to request instead of your app and maybe invalidate the analytics collected by watching the client. (I know it is a rare concern :D)

          1. 1

            I'm either not getting your question or you're confusing who is generating app_id and app_secret. That pair is generating by an Application and not by a User. So, app_secret is private to an application that makes requests to oAuth application on behalf of the user without sharing any private information of a user (e.g. password)