mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Revert "Revert "add oauth2-server""
This reverts commit 946a7c2494d39fd7581cb8a068af7df647fb3bda. GitOrigin-RevId: 2f02e9d9e2d0348e4ea1d447e0291fae72c0008a
This commit is contained in:
parent
9b24ed6daa
commit
7883554d73
7 changed files with 280 additions and 74 deletions
|
@ -187,8 +187,25 @@ module.exports = AuthenticationController =
|
||||||
return doRequest
|
return doRequest
|
||||||
|
|
||||||
requireOauth: () ->
|
requireOauth: () ->
|
||||||
|
# require this here because module may not be included in some versions
|
||||||
|
Oauth2Server = require "../../../../modules/oauth2-server/app/js/Oauth2Server"
|
||||||
return (req, res, next = (error) ->) ->
|
return (req, res, next = (error) ->) ->
|
||||||
return res.status(401).send() unless req.token?
|
request = new Oauth2Server.Request(req)
|
||||||
|
response = new Oauth2Server.Response(res)
|
||||||
|
Oauth2Server.server.authenticate request, response, {}, (err, token) ->
|
||||||
|
if err?
|
||||||
|
# fall back to v1 on invalid token
|
||||||
|
return AuthenticationController._requireOauthV1Fallback req, res, next if err.code == 401
|
||||||
|
# bubble up all other errors
|
||||||
|
return next(err)
|
||||||
|
req.oauth =
|
||||||
|
access_token: token.accessToken
|
||||||
|
req.oauth_token = token
|
||||||
|
req.oauth_user = token.user
|
||||||
|
return next()
|
||||||
|
|
||||||
|
_requireOauthV1Fallback: (req, res, next) ->
|
||||||
|
return res.sendStatus 401 unless req.token?
|
||||||
options =
|
options =
|
||||||
expectedStatusCodes: [401]
|
expectedStatusCodes: [401]
|
||||||
json: token: req.token
|
json: token: req.token
|
||||||
|
@ -199,11 +216,10 @@ module.exports = AuthenticationController =
|
||||||
return res.status(401).json({error: "invalid_token"}) unless body?.user_profile?.id
|
return res.status(401).json({error: "invalid_token"}) unless body?.user_profile?.id
|
||||||
User.findOne { "overleaf.id": body.user_profile.id }, (error, user) ->
|
User.findOne { "overleaf.id": body.user_profile.id }, (error, user) ->
|
||||||
return next(error) if error?
|
return next(error) if error?
|
||||||
return res.status(401).send({error: "invalid_token"}) unless user?
|
return res.status(401).json({error: "invalid_token"}) unless user?
|
||||||
req.oauth =
|
req.oauth =
|
||||||
access_token: body.access_token
|
access_token: body.access_token
|
||||||
collabratec_customer_id: body.collabratec_customer_id
|
user.collabratec_id = body.collabratec_customer_id unless user.collabratec_id?
|
||||||
user_profile: body.user_profile
|
|
||||||
req.oauth_user = user
|
req.oauth_user = user
|
||||||
next()
|
next()
|
||||||
|
|
||||||
|
|
31
services/web/app/coffee/models/OauthAccessToken.coffee
Normal file
31
services/web/app/coffee/models/OauthAccessToken.coffee
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
mongoose = require 'mongoose'
|
||||||
|
Settings = require 'settings-sharelatex'
|
||||||
|
|
||||||
|
Schema = mongoose.Schema
|
||||||
|
ObjectId = Schema.ObjectId
|
||||||
|
|
||||||
|
OauthAccessTokenSchema = new Schema(
|
||||||
|
{
|
||||||
|
accessToken: String
|
||||||
|
accessTokenExpiresAt: Date
|
||||||
|
oauthApplication_id: { type: ObjectId, ref: 'OauthApplication' }
|
||||||
|
refreshToken: String
|
||||||
|
refreshTokenExpiresAt: Date
|
||||||
|
scope: String
|
||||||
|
user_id: { type: ObjectId, ref: 'User' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
collection: 'oauthAccessTokens'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
conn = mongoose.createConnection(Settings.mongo.url, {
|
||||||
|
server: {poolSize: Settings.mongo.poolSize || 10},
|
||||||
|
config: {autoIndex: false}
|
||||||
|
})
|
||||||
|
|
||||||
|
OauthAccessToken = conn.model('OauthAccessToken', OauthAccessTokenSchema)
|
||||||
|
|
||||||
|
mongoose.model 'OauthAccessToken', OauthAccessTokenSchema
|
||||||
|
exports.OauthAccessToken = OauthAccessToken
|
||||||
|
exports.OauthAccessTokenSchema = OauthAccessTokenSchema
|
30
services/web/app/coffee/models/OauthApplication.coffee
Normal file
30
services/web/app/coffee/models/OauthApplication.coffee
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
mongoose = require 'mongoose'
|
||||||
|
Settings = require 'settings-sharelatex'
|
||||||
|
|
||||||
|
Schema = mongoose.Schema
|
||||||
|
ObjectId = Schema.ObjectId
|
||||||
|
|
||||||
|
OauthApplicationSchema = new Schema(
|
||||||
|
{
|
||||||
|
id: String
|
||||||
|
clientSecret: String
|
||||||
|
grants: [ String ]
|
||||||
|
name: String
|
||||||
|
redirectUris: [ String ]
|
||||||
|
scopes: [ String ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
collection: 'oauthApplications'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
conn = mongoose.createConnection(Settings.mongo.url, {
|
||||||
|
server: {poolSize: Settings.mongo.poolSize || 10},
|
||||||
|
config: {autoIndex: false}
|
||||||
|
})
|
||||||
|
|
||||||
|
OauthApplication = conn.model('OauthApplication', OauthApplicationSchema)
|
||||||
|
|
||||||
|
mongoose.model 'OauthApplication', OauthApplicationSchema
|
||||||
|
exports.OauthApplication = OauthApplication
|
||||||
|
exports.OauthApplicationSchema = OauthApplicationSchema
|
30
services/web/app/coffee/models/OauthAuthorizationCode.coffee
Normal file
30
services/web/app/coffee/models/OauthAuthorizationCode.coffee
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
mongoose = require 'mongoose'
|
||||||
|
Settings = require 'settings-sharelatex'
|
||||||
|
|
||||||
|
Schema = mongoose.Schema
|
||||||
|
ObjectId = Schema.ObjectId
|
||||||
|
|
||||||
|
OauthAuthorizationCodeSchema = new Schema(
|
||||||
|
{
|
||||||
|
authorizationCode: String
|
||||||
|
expiresAt: Date
|
||||||
|
oauthApplication_id: { type: ObjectId, ref: 'OauthApplication' }
|
||||||
|
redirectUri: String
|
||||||
|
scope: String
|
||||||
|
user_id: { type: ObjectId, ref: 'User' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
collection: 'oauthAuthorizationCodes'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
conn = mongoose.createConnection(Settings.mongo.url, {
|
||||||
|
server: {poolSize: Settings.mongo.poolSize || 10},
|
||||||
|
config: {autoIndex: false}
|
||||||
|
})
|
||||||
|
|
||||||
|
OauthAuthorizationCode = conn.model('OauthAuthorizationCode', OauthAuthorizationCodeSchema)
|
||||||
|
|
||||||
|
mongoose.model 'OauthAuthorizationCode', OauthAuthorizationCodeSchema
|
||||||
|
exports.OauthAuthorizationCode = OauthAuthorizationCode
|
||||||
|
exports.OauthAuthorizationCodeSchema = OauthAuthorizationCodeSchema
|
69
services/web/npm-shrinkwrap.json
generated
69
services/web/npm-shrinkwrap.json
generated
|
@ -2139,6 +2139,18 @@
|
||||||
"resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz",
|
||||||
"integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs="
|
"integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs="
|
||||||
},
|
},
|
||||||
|
"basic-auth": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"from": "basic-auth@>=2.0.0 <3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"from": "safe-buffer@5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"basic-auth-connect": {
|
"basic-auth-connect": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz",
|
||||||
|
@ -3550,6 +3562,16 @@
|
||||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||||
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
|
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
|
||||||
},
|
},
|
||||||
|
"co-bluebird": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"from": "co-bluebird@>=1.1.0 <2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/co-bluebird/-/co-bluebird-1.1.0.tgz"
|
||||||
|
},
|
||||||
|
"co-use": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"from": "co-use@>=1.1.0 <2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/co-use/-/co-use-1.1.0.tgz"
|
||||||
|
},
|
||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||||
|
@ -8431,6 +8453,11 @@
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"is-generator": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"from": "is-generator@>=1.0.2 <2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz"
|
||||||
|
},
|
||||||
"is-glob": {
|
"is-glob": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
|
||||||
|
@ -12576,6 +12603,43 @@
|
||||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
|
||||||
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
|
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
|
||||||
},
|
},
|
||||||
|
"oauth2-server": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"from": "oauth2-server@latest",
|
||||||
|
"resolved": "https://registry.npmjs.org/oauth2-server/-/oauth2-server-3.0.1.tgz",
|
||||||
|
"dependencies": {
|
||||||
|
"bluebird": {
|
||||||
|
"version": "3.5.3",
|
||||||
|
"from": "bluebird@>=3.5.1 <4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz"
|
||||||
|
},
|
||||||
|
"lodash": {
|
||||||
|
"version": "4.17.11",
|
||||||
|
"from": "lodash@>=4.17.10 <5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz"
|
||||||
|
},
|
||||||
|
"mime-db": {
|
||||||
|
"version": "1.38.0",
|
||||||
|
"from": "mime-db@>=1.38.0 <1.39.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz"
|
||||||
|
},
|
||||||
|
"mime-types": {
|
||||||
|
"version": "2.1.22",
|
||||||
|
"from": "mime-types@>=2.1.18 <2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz"
|
||||||
|
},
|
||||||
|
"statuses": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"from": "statuses@>=1.5.0 <2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz"
|
||||||
|
},
|
||||||
|
"type-is": {
|
||||||
|
"version": "1.6.16",
|
||||||
|
"from": "type-is@>=1.6.16 <2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
|
@ -14074,6 +14138,11 @@
|
||||||
"is-promise": "~1"
|
"is-promise": "~1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"promisify-any": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"from": "promisify-any@>=2.0.1 <3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/promisify-any/-/promisify-any-2.0.1.tgz"
|
||||||
|
},
|
||||||
"promisify-call": {
|
"promisify-call": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz",
|
||||||
|
|
|
@ -79,6 +79,7 @@
|
||||||
"nodemailer-sendgrid-transport": "^0.2.0",
|
"nodemailer-sendgrid-transport": "^0.2.0",
|
||||||
"nodemailer-ses-transport": "^1.3.0",
|
"nodemailer-ses-transport": "^1.3.0",
|
||||||
"nvd3": "^1.8.6",
|
"nvd3": "^1.8.6",
|
||||||
|
"oauth2-server": "^3.0.1",
|
||||||
"optimist": "0.6.1",
|
"optimist": "0.6.1",
|
||||||
"overleaf-error-type": "git+https://github.com/overleaf/overleaf-error-type.git",
|
"overleaf-error-type": "git+https://github.com/overleaf/overleaf-error-type.git",
|
||||||
"passport": "^0.3.2",
|
"passport": "^0.3.2",
|
||||||
|
|
|
@ -37,6 +37,10 @@ describe "AuthenticationController", ->
|
||||||
ipMatcherAffiliation: sinon.stub()
|
ipMatcherAffiliation: sinon.stub()
|
||||||
"../V1/V1Api": @V1Api = request: sinon.stub()
|
"../V1/V1Api": @V1Api = request: sinon.stub()
|
||||||
"../../models/User": { User: @UserModel }
|
"../../models/User": { User: @UserModel }
|
||||||
|
"../../../../modules/oauth2-server/app/js/Oauth2Server": @Oauth2Server =
|
||||||
|
Request: sinon.stub()
|
||||||
|
Response: sinon.stub()
|
||||||
|
server: authenticate: sinon.stub()
|
||||||
@user =
|
@user =
|
||||||
_id: ObjectId()
|
_id: ObjectId()
|
||||||
email: @email = "USER@example.com"
|
email: @email = "USER@example.com"
|
||||||
|
@ -402,16 +406,41 @@ describe "AuthenticationController", ->
|
||||||
|
|
||||||
describe "requireOauth", ->
|
describe "requireOauth", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
|
@res.sendStatus = sinon.stub()
|
||||||
@res.send = sinon.stub()
|
@res.send = sinon.stub()
|
||||||
@res.status = sinon.stub().returns(@res)
|
@res.status = sinon.stub().returns(@res)
|
||||||
@middleware = @AuthenticationController.requireOauth()
|
@middleware = @AuthenticationController.requireOauth()
|
||||||
|
|
||||||
|
describe "when Oauth2Server authenticates", ->
|
||||||
|
beforeEach ->
|
||||||
|
@token =
|
||||||
|
accessToken: "token"
|
||||||
|
user: "user"
|
||||||
|
@Oauth2Server.server.authenticate.yields null, @token
|
||||||
|
@middleware(@req, @res, @next)
|
||||||
|
|
||||||
|
it "should set oauth_token on request", ->
|
||||||
|
@req.oauth_token.should.equal @token
|
||||||
|
|
||||||
|
it "should set oauth on request", ->
|
||||||
|
@req.oauth.access_token.should.equal @token.accessToken
|
||||||
|
|
||||||
|
it "should set oauth_user on request", ->
|
||||||
|
@req.oauth_user.should.equal "user"
|
||||||
|
|
||||||
|
it "should call next", ->
|
||||||
|
@next.should.have.been.calledOnce
|
||||||
|
|
||||||
|
describe "when Oauth2Server does not authenticate", ->
|
||||||
|
beforeEach ->
|
||||||
|
@Oauth2Server.server.authenticate.yields code: 401
|
||||||
|
|
||||||
describe "when token not provided", ->
|
describe "when token not provided", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
@middleware(@req, @res, @next)
|
@middleware(@req, @res, @next)
|
||||||
|
|
||||||
it "should return 401 error", ->
|
it "should return 401 error", ->
|
||||||
@res.status.should.have.been.calledWith 401
|
@res.sendStatus.should.have.been.calledWith 401
|
||||||
|
|
||||||
describe "when token provided", ->
|
describe "when token provided", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
|
|
Loading…
Reference in a new issue