koa passport oauth2 save token to state

无人久伴 提交于 2020-04-17 19:05:31

问题


So I'm trying to save an access token to the state within Koa, just for use later and saving having to pass it around the client.

Following the passport oauth2 documentation for Koa, I'm struggling to persist anything to ctx.state...

Koa / passport oauth2 setup:

server.koaApp.use(koaSession(
  {
    key: sessionKey,
    rolling: true,
    maxAge: sessionMaxAge,
    sameSite: 'none',
    secure: true,
    // @ts-ignore
    domain: undefined
  },
  server.koaApp,
));

// set up passport sessions here
function createPassport() {
  const passport = new KoaPassport();

  passport.use(new OAuth2Strategy({
    authorizationURL: oauthClientAuthUrl,
    tokenURL: oauthClientTokenUrl,
    clientID: oauthClientId,
    clientSecret: oauthClientSecret,
    callbackURL: oauthClientRedirectUrl,
  }, function(accessToken, refreshToken, params, profile, cb) {
    cb(null, {id: 'somedudesID', accessToken});
  }));

  passport.serializeUser((user, done) => {
    done(null, user);
  });

  passport.deserializeUser((user, done) => {
    done(null, user);
  });

  return passport;
};

Route declarations that should set and read accesstoken:

router.get('/authorize', passport.authenticate('oauth2'), (ctx: any) => {
        const { accessToken } = ctx.session.passport.user;
        ctx.state.accessToken = accessToken;
        ctx.status = 200;
      });

    router.get('/get-token-from-state', (ctx: any) => {
      console.log(ctx.state.accessToken); // undefined
    });

Questions:

  1. Why is ctx.state.accessToken undefined when doing a get to /get-token-from-state?

  2. Should I even be trying to persist the access token like this? Is there another way to obtain the accessToke in other routes?


回答1:


I had the same annoying experience. What helped was removing koa-session and replace it with koa-generic-session. Then I setup a memory store -> now it works :)

Iam not sure if storing the token inside a memory session is the best idea - but right now its my first draft. Its only a little code block to get in touch with keycloak.

server.js

    var app = new Koa();
    app.keys = ['keys', 'keykeys'];
    var memoryStore = new session.MemoryStore();

    // Session
    app.use(session({
        secret: 'some secret',
        resave: false,
        saveUninitialized: true,
        store: memoryStore
      }));

    // Passport
    const passport = require('./oauth2')
    app.use(passport.initialize());
    app.use(passport.session());

oauth2.js

const request = require('request');
const passport = require('koa-passport');
const OAuth2Strategy = require('passport-oauth2').Strategy;


const clientId = "b2m";
const clientSecrect = "57ce5bba-f336-417f-b9c2-06157face88f";

OAuth2Strategy.prototype.userProfile = function (accessToken, done) {
  var options = {
      url: 'http://localhost:8080/auth/realms/master/protocol/openid-connect/userinfo',
      headers: {
          'User-Agent': 'request',
          'Authorization': 'Bearer ' + accessToken,
      }
  };

  request(options, callback);

  function callback(error, response, body) {
      if (error || response.statusCode !== 200) {
          return done(error);
      }
      var info = JSON.parse(body);
      return done(null, info);
  }
};

passport.use(new OAuth2Strategy({
    authorizationURL: 'http://localhost:8080/auth/realms/master/protocol/openid-connect/auth',
    tokenURL: 'http://localhost:8080/auth/realms/master/protocol/openid-connect/token',
    clientID: clientId,
    clientSecret: clientSecrect,
    callbackURL: "http://localhost:3000/callback"
  },
  function(accessToken, refreshToken, profile, cb) {
    console.log('#########################################################');
    console.log('Authenticated with OAuth2');
    console.log('accessToken', accessToken);
    console.log('refreshToken', refreshToken);
    
    var user = {
      accessToken: accessToken,
      refreshToken: refreshToken,
      profile: profile
    };
    console.log('user', user);

    return cb(null, user);
  }
));

/* Example: storing user data received from the strategy callback in the session, i.e. in `req.session.passport.user` */
passport.serializeUser(function(user, done) {
    done(null, user);
  });
  
/* Example: getting the user data back from session and attaching it to the request object, i.e. to `req.user` */
passport.deserializeUser(function (user, next) {
    /*
      Example: if only a user identifier is stored in the session, this is where
      the full set could be retrieved, e.g. from a database, and passed to the next step
    */
    next(null, user);
});

module.exports = passport;



回答2:


So, answering my own question here, it was a number of things:

  1. "sameSite: 'lax'" was needed
  2. Cookies of the session were not being saved in browser because the domains were slightly off (port numbers were different.

I was able to proxy this locally and all good!



来源:https://stackoverflow.com/questions/60709882/koa-passport-oauth2-save-token-to-state

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!