• Cosimo Orban

Basically Auth

Swagga talks about several issues with Basic Auth.

  • Replay attacks

  • Sending credentials in the clear over HTTP due to user error

  • Large attack surface by sending auth in every request

Other sites talk about

  • Capturing credentials in plaintext logs

Let's look at the workflow for OAuth which is doing something similar to our use case: allowing a user to authorize some credentials to make requests on their behalf.

OAuth has three parties, the server, the client and the user. The server contains the resources we want. The client is the application that wants to access those resources. The user is the one who is allowed to authorize the client.

The client starts by having a trusted communication with the server to establish a client_id and client_secret. This is then a shared secret between the server and client. Let's assume the values are my-id and secret - it makes the examples easier to follow

Next the client makes a request to the server to ask for an authorization code.

GET /o/oauth2/auth?

There's other stuff in there about redirects and state and things, but that's really it, client my-id wants an auth code with access to all-yer-data. This request is handled by a browser is one fashion or another. Then your browser does something and your application is supposed to get the code out of it. When I say 'something' I really mean it - there's lots of techniques based on the exact platform for how to get the code out of the browser ranging from deploying a local web server to reading the window title using OS-level calls to enumerate windows. That's on Windows. Go figure.

Now your application has a code. They expire, so use it fast.

POST /oauth2/v3/token
    "code"          : "abc-123",
    "client_id"     : "my-id",
    "client_secret" : "secret",

Again, there's some other stuff in there, but that's the essential. Send the code off with our shared secret information to get a token. Response looks like this:

    "access_token"  : "some-token",
    "refresh_token" : "another-token",
    "expires_in"    : 20

Alright, now you have two tokens. The access_token you can use immediately to operate on behalf of the user. The refresh_token you use to get new access_tokens.

POST /oauth2/v3/token
    "refresh_token" : "another-token",
    "client_id"     : "my-id",
    "client_secret" : "secret",

Then the response will look like this

    "access_token"  : "brand-new-token",
    "expires_in"    : 100

The refresh token doesn't expire. It can be revoked by the user.

What happened here is essentially a permissions bootstrapping process. We have a shared secret between the client and server to identify the client. We have a very time-limited window where the user produces the code and the client uses that code to create a new shared secret, the refresh token, which is used to create auth tokens for use in normal exchanges. That's the basic flow.

So, what are some of the avenues for attack? Well, if we can read the token refresh request we can get the client_id and refresh token and either deny service (if throttled) or impersonate the client and do Nefarious Things(tm). We mitigate that by making the tokens last longer so there are fewer refresh requests. On the flip side we could read a single regular request and get a hold of the auth token. Then we can either deny service (if throttled) or impersonate the client as long as the token lasts. This is less bad since we know the token has a limited lifespan. Still, replay attacks are a thing here, especially if the token is passed in a URL as a query arg where it may be logged.

Let's try this with basic auth. The user authenticates a session and proactively creates a new api-token

POST /api-key/


X-Api-Key: abc-123
X-Api-Key-Secret: 111-222

This generates a token that serves the same purpose as refresh_token/client_id.

5 views0 comments

Recent Posts

See All

ES6 features to start with

Arrows => Arrows are a shorthand for function. Old way: users.forEach(function(user) { // do something with the user }); New way: users.forEach(user => { // do something with the user }) Impor

Follow us at:

  • LinkedIn
  • Twitter
  • YouTube
  • Facebook

Contact Us

Philadelphia, PA, USA

aMES for OEMs

aMES for Service Bureaus

Extension Modules


Company Overview


Member of



Machine Integrations

Software Integrations

Privacy Policy

Terms of Use