requarks / wiki-v1

Legacy version (1.x) of Wiki.js
https://wiki.js.org
GNU Affero General Public License v3.0
101 stars 75 forks source link

Add scopes to OIDC config #149

Open grugknuckle opened 5 years ago

grugknuckle commented 5 years ago

I am using ver 1.0.102 and I can see that it has implemented Open ID Connect with the passport-openidconnect module.

Specifically, I'm reading lines 230 - 255 of the code here.

  // OpenID Connect

  if (appconfig.auth.oidc && appconfig.auth.oidc.enabled) {
    const OIDCStrategy = require('passport-openidconnect').Strategy
    passport.use('oidc', new OIDCStrategy({
      userInfoURL: appconfig.auth.oidc.userInfoUrl,
      authorizationURL: appconfig.auth.oidc.authorizationURL,
      tokenURL: appconfig.auth.oidc.tokenURL,
      clientID: appconfig.auth.oidc.clientId,
      clientSecret: appconfig.auth.oidc.clientSecret,
      issuer: appconfig.auth.oidc.issuer,
      callbackURL: appconfig.host + '/login/oidc/callback'
    }, (iss, sub, profile, jwtClaims, accessToken, refreshToken, params, cb) => {
      db.User.processProfile({
        id: jwtClaims.sub,
        provider: 'oidc',
        email: _.get(jwtClaims, appconfig.auth.oidc.emailClaim),
        name: _.get(jwtClaims, appconfig.auth.oidc.usernameClaim)
      }).then((user) => {
        return cb(null, user) || true
      }).catch((err) => {
        return cb(err, null) || true
      })
    }
    ))
  }

In the .processProfile method, the OIDC strategy is attempting extracting the email address from the jwtClaims object. However, the request being sent to the openid provider is only adding the 'openid' scope. It does NOT add the 'email' or 'profile' claim to the scopes. My openid provider (Okta) does NOT put the email into the id token unless I request the 'email' scope. But the code above does not provide a way for a developer to add this scope to the request.

Note that the passport-openidconnect module, which is being used by wiki.js, does support adding the scope to the strategy options when the passport strategy is initialized. You can read that source code here, it's line 34.

So I'm simply requesting that you change the code above in the [auth.js file] (https://github.com/Requarks/wiki/blob/73cd6af5b7b3338ff30e9466a8da9074cf9bbfad/server/libs/auth.js) to

  // OpenID Connect

  if (appconfig.auth.oidc && appconfig.auth.oidc.enabled) {
    const OIDCStrategy = require('passport-openidconnect').Strategy
    passport.use('oidc', new OIDCStrategy({
      userInfoURL: appconfig.auth.oidc.userInfoUrl,
      authorizationURL: appconfig.auth.oidc.authorizationURL,
      tokenURL: appconfig.auth.oidc.tokenURL,
      clientID: appconfig.auth.oidc.clientId,
      clientSecret: appconfig.auth.oidc.clientSecret,
      issuer: appconfig.auth.oidc.issuer,
      /*  ADD THE SCOPE OPTION ! */
      scope: appconfig.auth.oidc.scope,
      callbackURL: appconfig.host + '/login/oidc/callback'
    }, (iss, sub, profile, jwtClaims, accessToken, refreshToken, params, cb) => {
      db.User.processProfile({
        id: jwtClaims.sub,
        provider: 'oidc',
        email: _.get(jwtClaims, appconfig.auth.oidc.emailClaim),
        name: _.get(jwtClaims, appconfig.auth.oidc.usernameClaim)
      }).then((user) => {
        return cb(null, user) || true
      }).catch((err) => {
        return cb(err, null) || true
      })
    }
    ))
  }

And then the in the config.sample.yml file, set the default oidc object to

oidc:
    enabled: false
    clientId: OPENID_CONNECT_CLIENT_ID
    clientSecret: OPENID_CONNECT_CLIENT_SECRET
    issuer: OPENID_CONNECT_ISSUER
    scope: 'openid'
    userInfoUrl: OPENID_CONNECT_USER_INFO_URL
    authorizationURL: OPENID_CONNECT_AUTHORIZATION_URL
    tokenURL: OPENID_CONNECT_TOKEN_URL
    emailClaim: OPENID_CONNECT_EMAIL_CLAIM_PATH
    usernameClaim: OPENID_CONNECT_USERNAME_CLAIM_PATH

This will allow developers to modify the scopes as required by their particular OIDC provider.

NOTE: For my personal use of wiki.js, I used the heroku deploy widget. That project has an install script which automagically downloads and installs the latest release of wiki.js from a tar.gz. So for users like me, it is necessary that this release is up to date.