swagger-api / swagger-codegen

swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.
http://swagger.io
Apache License 2.0
16.79k stars 6.02k forks source link

[JavaScript] Dynamically compute auth header? #8287

Open john-goldsmith opened 6 years ago

john-goldsmith commented 6 years ago

I have what I suspect to be an "Authentication 101" type question, but am unsure of the approach when using a generated JavaScript client in the context of a SPA (React, specifically). I configure my SDK client-side to pass along a JWT which works fine, and my API is setup to handle token expiration, but I'm wondering what should happen if the user forcibly removes their token from local storage? The scenario in my mind:

  1. User logs in successfully (token is supplied, put in local storage, and SDK client configured)
  2. User clears browser storage via DevTools, etc.
  3. User performs interaction that issues an XHR using the SDK client
  4. XHR succeeds because token is saved on the SDK client

Per the generated README.md, I configure my SDK client like this:

function authenticate(email, password) {
  // Pass off to API and get a response...
  const { jwt } = apiResponse.body;
  window.localStorage.setItem('jwt', jwt);

  // Configure the SDK to use the apiKey security definition
  const defaultClient = MySdk.ApiClient.instance;
  const jwtAuth = defaultClient.authentications['jwt'];
  jwtAuth.apiKey = jwt; // Cached on client
}

My off-the-cuff idea would be to allow authentication keys to be set as functions which get invoked prior to firing off the XHR:

jwtAuth.apiKey = () => window.localStorage.getItem('jwt');
if (typeof jwtAuth.apiKey === 'function') {
  return jwtAuth.apiKey();
} else {
  return jwtAuth.apiKey
}

Other ideas that came to mind:

  1. Functionality might already exist for other custom (non-auth) headers?
  2. Tap into the React component lifecycle and check for existence (outside the scope of swagger-codegen)
  3. Add superagent request interceptor

Any input on this is appreciated!

jaaufauvre commented 5 years ago

You can override applyAuthToRequest the following way:

const apiClient = require('../service/ApiClient.js');
const client = apiClient.instance;
client.applyAuthToRequest = function(request) {
    const _end = request._end;
    request._end = function() {
        request.req.setHeader('Authorization', computeAuthorizationHeader(request));
        _end.call(request);
    }
    return request;
};