Search code examples
c#asp.netoauthjwtumbraco

Client IDs and secrets


Request URL:
POST https://example.com/oauth/token
Request Headers:
  Content-Type: application/x-www-form-urlencoded
Request POST Body:
grant_type=password&username=joebloggs&
   password=password1234&client_id=myclient&client_secret=myclientsecret

Response:
{
  "access_token": "omitted for brevity",
  "token_type": "bearer",
  "expires_in": 1200,
  "refresh_token": "b3cc9c66b86340c5b743f2a7cec9d2f1"
}

I would like to protect my Umbraco web api endpoints using a JWT sent from a single page app. I found this lib to cover most of my needs.

Since I make use of the InMemoryOAuthClientStore the documentation states that a client id and secret must be provided with the authentication request (I presume this is used to match an OAuthClient in the store?):

client_id = A valid client id (Only required if a client store is configured)

client_secret = A valid client secret (Only required if a client store is configured, and the client is "secure")

I would like to know how they are intended to be used. If I make this authorization call to https://example.com/oauth/token using an AJAX call from the client, I need to store the id and secret on the client side. My gut feeling tells me that's not how it's intended to be used.

On the other hand, the client id and secret are accompanied with user credentials in this case, so they're worthless without a valid username and password.

Someone please shed some light on this.


Solution

  • Some clients are capable of keeping some information (client secret) private and some do not. For example, if you make request to oauth endpoint directly from javascript via ajax - this client is not "secure". It's not capable of storing client secret privately, because anyone can see this secret either in javascript code directly or by observing request in browser dev tools. For such clients (mobile applications is another example) it does not make any sense to use client secret in any flow, including "password" flow.

    Example of "secure" client is web server you own. So you don't make request to oauth endpoint directly from javascript but instead you send credentials to your server, and then server makes request to oauth endpoint. This client is "secure" in a sense it is capable of privately storing client secret. For such clients it does make sense (and even required I'd say) to require client secret.

    So in short, your gut feeling is correct - you should not use client secret in your case, because it does nothing useful.

    Now, even if you don't use client secret, you still can use client_id alone. For example you might issue a different set of claims for different clients. Just note that client id is public info, so you should not make any sensitive decisions based on client_id alone - it cannot be trusted.

    Also note that "password" flow is the last resort and should only be used by clients you own, and when no other flow is available.