2
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.

VDWWD
  • 35,079
  • 22
  • 62
  • 79
Johan
  • 35,120
  • 54
  • 178
  • 293

2 Answers2

2

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.

Evk
  • 98,527
  • 8
  • 141
  • 191
  • Thanks for the explanation. I guess it comes down to a limitation of the library then, because as you're saying, I don't need the secret, but I'm required to use it since I want to use the `InMemoryOAuthClientStore`. – Johan Jan 22 '18 at 08:28
  • @Johan maybe you can describe your case in more details. As far as I understood - you have just one client, which is your own single page web application. – Evk Jan 22 '18 at 08:35
  • Right. In the long run my customer wants to be able to generate tokens from an external system too. My idea was to use a common secret between our applications to generate the tokens. To be able to define a token secret in this lib I must define it in a client, which is passed to the `InMemoryOAuthClientStore`. But maybe it would be a better solution to keep the token creation on my application, and let them generate a token through my API, securing it with an API-key, basic auth or something similar? – Johan Jan 22 '18 at 09:46
  • @Johan I don't know much (actually anything) about Umbarco, but this lib seems to allow you to define insecure client (OAuthClient has SecurityLevel property), for which client secret should not be required to pass. So you can use one client for your applicaiton (insecure) and another for your customer (secure). But note that you should not use "password" flow for third party clients (like your customer app), because you should not leak your users passwords to third party. – Evk Jan 22 '18 at 10:14
  • Right. Thanks a lot for your time, I have the answers I was looking for now :) Can't give you the bounty for another 3 hours apparently – Johan Jan 22 '18 at 11:38
1

There are 2 main reasons to request a token with a username and password and then storing that token on the requesting end.

  1. Extra security. A username/password combo is not send with every request but only once every 1200 seconds/minutes.
  2. The server handling the request only needs to check the validity of the token instead of a performance heavy password hash for every request.

There are other reasons as well, please see the links below.

Update

The client_id is a public identifier for apps. The client_secret is a secret known only to the application and the authorization server. More info in the following links.

VDWWD
  • 35,079
  • 22
  • 62
  • 79
  • I'm asking for some clarification regarding the client id and secret and how they should be used - not about tokens in general – Johan Jan 21 '18 at 17:52
  • Updated my answer. – VDWWD Jan 21 '18 at 18:21
  • Thanks. Could you elaborate "secure client"? As far as I know, there is no such thing... ("Only required if a client store is configured, and the client is "secure" ") – Johan Jan 21 '18 at 18:42