simov / grant

OAuth Proxy
MIT License
4.09k stars 257 forks source link

Working with rotating client id and client secret #224

Open nebularazer opened 3 years ago

nebularazer commented 3 years ago

Hi,

i have a custom oauth2 provider which rotates the client_secret on a regular basis. This client_secret is updated in a file, so i have to read that secret before each authorization request in case it changed.

Is there a way to achieve that with grant?

Thanks in advance.

simov commented 3 years ago

Yes, and since the is your client secret, the best way to do this is by using the Dynamic State Overrides. You can play around with it using the examples for it.

The gist of it is that you read the secret in a middleware preceding the Grant one, and set it in a certain way so Grant can read it after that.

Let me know if you have any questions.

nebularazer commented 3 years ago

Hi simov,

thank you very much for your response, i looked at dynamic overwrites but did not understand the power of it before looking at the examples.

I managed to get it working, but the response is missing the tokens. Can you see what i am missing here?

import { readFileSync } from 'fs';
import https from 'https';

import express from 'express';
import grant from 'grant';
import session from 'cookie-session';

const app = express();

app.use(
  session({
    name: 'session',
    secret: 'keyboard cat',
  }),
);

// grant
app.use('/connect/example', (req, res, next) => {
  const clientId = readFileSync(
    'credentials/client-id',
    'utf8',
  ).trim();
  const clientSecret = readFileSync(
    'credentials/client-secret',
    'utf8',
  ).trim();
  res.locals.grant = { dynamic: { key: clientId, secret: clientSecret } };
  next();
});

app.use(
  grant.express({
    example: {
      transport: 'session',
      access_url: 'https://example.com/oauth2/token',
      authorize_url: 'https://example.com/oauth2/authorize',
      oauth: 2,
      origin: 'https://localhost',
      custom_params: {
        partner_id: '8143d3fdd24c7',
      },
      redirect_uri: 'https://localhost/login',
    },
  }),
);

// routes
// login comes back with /login?state=&code=eyJl...[snip]...pC88o
app.get('/login', (req, res, next) => {
  // see snipped below for result of console.log
  console.log(req.session!.grant)
  res.json({ a: 1 });
});

const sslOptions = {
  key: readFileSync('key.pem'),
  cert: readFileSync('cert.pem'),
  passphrase: '1234',
};

// my provider only allows https redirect uris
https.createServer(sslOptions, app).listen(443);
{
  provider: 'example',
  response: 'https://example.com/oauth2/authorize?client_id=my_client_id&response_type=code&redirect_uri=https%3A%2F%2Flocalhost%2Flogin&partner_id=8143d3fdd24c7'
}
simov commented 3 years ago

The redirect_uri should be the redirect URI of your OAuth application, the one you set for your application in the providers dashboard. The /login path on your server should be the callback configuration instead.

Generally speaking specifying the redirect_uri explicitly is not even required because it have to follow certain path structure that Grant will generate for your redirect_uri.

nebularazer commented 3 years ago

Thank you so much, i got it working now. I did not correctly understood how redirect_url and callback is connected to each other. Now i know that endpoint of redirect_url redirects again to the callback URL and only at this point the data is available.

Thanks again for your awesome support!