mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-14 15:14:56 -04:00
Add oauth2 authorization
Signed-off-by: Joachim Mathes <joachim_mathes@web.de>
This commit is contained in:
parent
c59d4c7c5c
commit
729b387536
3 changed files with 29 additions and 2 deletions
|
@ -189,12 +189,15 @@ these are rarely used for various reasons.
|
||||||
| | `CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR` | **no default**, `name` | where to find the username in the JSON from the user profile URL. (no default value) |
|
| | `CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR` | **no default**, `name` | where to find the username in the JSON from the user profile URL. (no default value) |
|
||||||
| | `CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR` | **no default**, `display-name` | where to find the display-name in the JSON from the user profile URL. (no default value) |
|
| | `CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR` | **no default**, `display-name` | where to find the display-name in the JSON from the user profile URL. (no default value) |
|
||||||
| | `CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR` | **no default**, `email` | where to find the email address in the JSON from the user profile URL. (no default value) |
|
| | `CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR` | **no default**, `email` | where to find the email address in the JSON from the user profile URL. (no default value) |
|
||||||
|
| | `CMD_OAUTH2_USER_PROFILE_ID_ATTR` | **no default**, `user_uuid` | where to find the dedicated user ID (optional, overrides `CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR`) |
|
||||||
| | `CMD_OAUTH2_TOKEN_URL` | **no default**, `https://example.com` | sometimes called token endpoint, please refer to the documentation of your OAuth2 provider (no default value) |
|
| | `CMD_OAUTH2_TOKEN_URL` | **no default**, `https://example.com` | sometimes called token endpoint, please refer to the documentation of your OAuth2 provider (no default value) |
|
||||||
| | `CMD_OAUTH2_AUTHORIZATION_URL` | **no default**, `https://example.com` | authorization URL of your provider, please refer to the documentation of your OAuth2 provider (no default value) |
|
| | `CMD_OAUTH2_AUTHORIZATION_URL` | **no default**, `https://example.com` | authorization URL of your provider, please refer to the documentation of your OAuth2 provider (no default value) |
|
||||||
| | `CMD_OAUTH2_CLIENT_ID` | **no default**, `afae02fckafd...` | you will get this from your OAuth2 provider when you register HedgeDoc as OAuth2-client, (no default value) |
|
| | `CMD_OAUTH2_CLIENT_ID` | **no default**, `afae02fckafd...` | you will get this from your OAuth2 provider when you register HedgeDoc as OAuth2-client, (no default value) |
|
||||||
| | `CMD_OAUTH2_CLIENT_SECRET` | **no default**, `afae02fckafd...` | you will get this from your OAuth2 provider when you register HedgeDoc as OAuth2-client, (no default value) |
|
| | `CMD_OAUTH2_CLIENT_SECRET` | **no default**, `afae02fckafd...` | you will get this from your OAuth2 provider when you register HedgeDoc as OAuth2-client, (no default value) |
|
||||||
| | `CMD_OAUTH2_PROVIDERNAME` | **no default**, `My institution` | Optional name to be displayed at login form indicating the oAuth2 provider |
|
| | `CMD_OAUTH2_PROVIDERNAME` | **no default**, `My institution` | Optional name to be displayed at login form indicating the oAuth2 provider |
|
||||||
| | `CMD_OAUTH2_SCOPE` | **no default**, `openid email profile` | Scope to request for OIDC (OpenID Connect) providers. |
|
| | `CMD_OAUTH2_SCOPE` | **no default**, `openid email profile` | Scope to request for OIDC (OpenID Connect) providers. |
|
||||||
|
| | `CMD_OAUTH2_ROLES_CLAIM` | **no default**, `roles` | ID token claim, which is supposed to provide an array of strings of roles |
|
||||||
|
| | `CMD_OAUTH2_ACCESS_ROLE` | **no default**, `role/hedgedoc` | The role which should be included in the ID token roles claim to grant access |
|
||||||
|
|
||||||
### SAML Login
|
### SAML Login
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,7 @@ module.exports = {
|
||||||
providerName: process.env.CMD_OAUTH2_PROVIDERNAME,
|
providerName: process.env.CMD_OAUTH2_PROVIDERNAME,
|
||||||
baseURL: process.env.CMD_OAUTH2_BASEURL,
|
baseURL: process.env.CMD_OAUTH2_BASEURL,
|
||||||
userProfileURL: process.env.CMD_OAUTH2_USER_PROFILE_URL,
|
userProfileURL: process.env.CMD_OAUTH2_USER_PROFILE_URL,
|
||||||
|
userProfileIdAttr: process.env.CMD_OAUTH2_USER_PROFILE_ID_ATTR,
|
||||||
userProfileUsernameAttr: process.env.CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR,
|
userProfileUsernameAttr: process.env.CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR,
|
||||||
userProfileDisplayNameAttr: process.env.CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR,
|
userProfileDisplayNameAttr: process.env.CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR,
|
||||||
userProfileEmailAttr: process.env.CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR,
|
userProfileEmailAttr: process.env.CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR,
|
||||||
|
@ -94,7 +95,9 @@ module.exports = {
|
||||||
authorizationURL: process.env.CMD_OAUTH2_AUTHORIZATION_URL,
|
authorizationURL: process.env.CMD_OAUTH2_AUTHORIZATION_URL,
|
||||||
clientID: process.env.CMD_OAUTH2_CLIENT_ID,
|
clientID: process.env.CMD_OAUTH2_CLIENT_ID,
|
||||||
clientSecret: process.env.CMD_OAUTH2_CLIENT_SECRET,
|
clientSecret: process.env.CMD_OAUTH2_CLIENT_SECRET,
|
||||||
scope: process.env.CMD_OAUTH2_SCOPE
|
scope: process.env.CMD_OAUTH2_SCOPE,
|
||||||
|
rolesClaim: process.env.CMD_OAUTH2_ROLES_CLAIM,
|
||||||
|
accessRole: process.env.CMD_OAUTH2_ACCESS_ROLE
|
||||||
},
|
},
|
||||||
dropbox: {
|
dropbox: {
|
||||||
clientID: process.env.CMD_DROPBOX_CLIENTID,
|
clientID: process.env.CMD_DROPBOX_CLIENTID,
|
||||||
|
|
|
@ -4,6 +4,7 @@ const Router = require('express').Router
|
||||||
const passport = require('passport')
|
const passport = require('passport')
|
||||||
const { Strategy, InternalOAuthError } = require('passport-oauth2')
|
const { Strategy, InternalOAuthError } = require('passport-oauth2')
|
||||||
const config = require('../../../config')
|
const config = require('../../../config')
|
||||||
|
const logger = require('../../../logger')
|
||||||
const { passportGeneralCallback } = require('../utils')
|
const { passportGeneralCallback } = require('../utils')
|
||||||
|
|
||||||
let oauth2Auth = module.exports = Router()
|
let oauth2Auth = module.exports = Router()
|
||||||
|
@ -31,6 +32,7 @@ class OAuth2CustomStrategy extends Strategy {
|
||||||
return done(new Error('Failed to parse user profile'))
|
return done(new Error('Failed to parse user profile'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkAuthorization(json, done)
|
||||||
let profile = parseProfile(json)
|
let profile = parseProfile(json)
|
||||||
profile.provider = 'oauth2'
|
profile.provider = 'oauth2'
|
||||||
|
|
||||||
|
@ -50,18 +52,36 @@ function extractProfileAttribute (data, path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseProfile (data) {
|
function parseProfile (data) {
|
||||||
|
const id = extractProfileAttribute(data, config.oauth2.userProfileIdAttr)
|
||||||
const username = extractProfileAttribute(data, config.oauth2.userProfileUsernameAttr)
|
const username = extractProfileAttribute(data, config.oauth2.userProfileUsernameAttr)
|
||||||
const displayName = extractProfileAttribute(data, config.oauth2.userProfileDisplayNameAttr)
|
const displayName = extractProfileAttribute(data, config.oauth2.userProfileDisplayNameAttr)
|
||||||
const email = extractProfileAttribute(data, config.oauth2.userProfileEmailAttr)
|
const email = extractProfileAttribute(data, config.oauth2.userProfileEmailAttr)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: username,
|
id: id || username,
|
||||||
username: username,
|
username: username,
|
||||||
displayName: displayName,
|
displayName: displayName,
|
||||||
email: email
|
email: email
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkAuthorization (data, done) {
|
||||||
|
const roles = extractProfileAttribute(data, config.oauth2.rolesClaim)
|
||||||
|
const username = extractProfileAttribute(data, config.oauth2.userProfileUsernameAttr)
|
||||||
|
|
||||||
|
if (config.oauth2.accessRole) {
|
||||||
|
if (!roles) {
|
||||||
|
logger.error('oauth2: "accessRole" configured, but user profile doesn\'t contain roles attribute. Permission denied')
|
||||||
|
return done('Permission denied', null)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!roles.includes(config.oauth2.accessRole)) {
|
||||||
|
logger.debug(`oauth2: user "${username}" doesn't have the required role. Permission denied`)
|
||||||
|
return done('Permission denied', null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
OAuth2CustomStrategy.prototype.userProfile = function (accessToken, done) {
|
OAuth2CustomStrategy.prototype.userProfile = function (accessToken, done) {
|
||||||
this._oauth2.get(this._userProfileURL, accessToken, function (err, body, res) {
|
this._oauth2.get(this._userProfileURL, accessToken, function (err, body, res) {
|
||||||
var json
|
var json
|
||||||
|
@ -76,6 +96,7 @@ OAuth2CustomStrategy.prototype.userProfile = function (accessToken, done) {
|
||||||
return done(new Error('Failed to parse user profile'))
|
return done(new Error('Failed to parse user profile'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkAuthorization(json, done)
|
||||||
let profile = parseProfile(json)
|
let profile = parseProfile(json)
|
||||||
profile.provider = 'oauth2'
|
profile.provider = 'oauth2'
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue