Is PKCE really protecting public facing clients? Can't a rogue app steal the ClientID and Secret?

  • From what I have understood, for public facing clients such as JavaScript apps that run on the browser or mobile apps which have no backend there is no secure place to store client id and secret. Therefore, the client will generate a random string code a.k.a code challenge (plain).

    And then:

    Client sends ClientID, secret, redirect URI and code challenge --> Authorization Server 
    --> Auth Server sends back Auth Code --> Client --> Sends the previously generated code challenge (string) 
    --> Auth Server --> Auth Server checks if the code challenge is same as the one that was sent earlier
     when it generated that particular Auth Code. --> Auth Server Sends back Access token.

    How does this secure the client application? I mean that if someone can steal the ClientID and secret then it can also generate a random string and send all three to the Authorization server to generate Auth Code and then make another request to get the access token. Eventually the token would expire and then the person could repeat the process since it has the ClientID and Secret. It is just a matter of generating that random code challenge again.

    I understand that Hacker App can not use the stolen AuthCode to get Access Token because of PKCE but - why can't Hacker app use the clientID of your app and generate a code verifier then ask Authorization Server for a Auth Code and then again for Access Code?

    Is it impossible to steal ClientID? When Authorization sever sends back the AuthCode to the client. Is that the only point which is vulnerable?

    I have been through this post but I am still not clear on this.

  • Taking you to be asking two questions, what does pkce guard against, and how is client_id being random offering any protection to you if people can just lift it out of your source code, this is my understanding:

    why does pkce even exist:

    the whole reason for pkce is due to the nature that mutliple smartphone apps can register themselves to be "handlers" of specific url patterns, (this is a vulnerability that only exists in smartphones, if you're making a single page app this is not really a vulnerability for you though I think the advice is to use PKCE if you aren't using a client secret regardless, also it's harmless to use PKCE regardless because it won't ruin anything if you use it and the server doesn't support it)

    why bad on smartphone:

    when the oauth2 service redirects the user back to your app, following your apps pre-registered redirection url, the browser on the smartphone is going to attempt to navigate to that url, at that point the operating system detects this (both android and ios work this way) and notices that it matches with a few apps already registered at installation time to handle such urls, and it could automatically pass it to the wrong app, which could then maliciously act to get an access token with that and start doing bad stuff in the name of the user.

    why should client id be random if it can easily be lifted: from the docs here:

    "If the client ID is guessable, it makes it slightly easier to craft phishing attacks against arbitrary applications."

    So my guess is being random basically just adds another level of effort for a malware author to put in in order to write something that would affect your app. (you won't be protected from a malware author that targets your app, but you would be protected from a malware author that is blanket targeting all apps say on an appstore...)

    The other part to the question, whats to stop an attacker from stealing your clientId and making a request to the auth server masquerading as your app. This won't work because of the redirection URL's.

    it is critical that the service doesn’t redirect the user to arbitrary locations

    If a user visits the attackers app, and is redirected to the auth server to authenticate but the redirect made use of your apps clientId, then the auth server would redirect the user back to your app, not the attackers, see the security considerations of the docs:

    The only way the authorization code grant with no client secret can be secure is by using the “state” parameter and restricting the redirect URL to trusted clients.

    What they mean by using the state parameter is that your app can make use of local persistent storage (like local storage for a webpage) to generate a random string that it would include in the state param of the redirect request, and if the auth server redirects the user back to your app/web app after the user authenticates, it will echo back the state param and your app should verify that the value in that matches a recently previously stored state random string in said local storage or similar to have a confidence that the user being redirected back to your app was the result of an auth flow that was indeed kicked off by your app and not an attackers app, (if the redirection has no state param or a state param that doesn't match anything in the apps local storage then at that point your app should know that it wasn't itself that initiated that auth flow, and so should not consider the user as having completed the flow properly (should not proceed to trade the auth code for a token)

Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2