UNPKG

@quarks/quarks-iam

Version:

A modern authorization server built to authenticate your users and protect your APIs

536 lines (394 loc) 14.7 kB
chai = require 'chai' sinon = require 'sinon' sinonChai = require 'sinon-chai' expect = chai.expect chai.use sinonChai chai.should() IDToken = require '../../../models/IDToken' AccessToken = require '../../../models/AccessToken' AuthorizationCode = require '../../../models/AuthorizationCode' authorize = require('../../../oidc').authorize describe 'Authorize', -> {req,res,next,err} = {} describe 'with consent and "code" response type', -> before (done) -> sinon.stub(AuthorizationCode, 'insert').callsArgWith(1, null, { code: '1234' }) req = session: {} client: _id: 'uuid1' user: _id: 'uuid2' connectParams: authorize: 'true' response_type: 'code' redirect_uri: 'https://host/callback' state: 'r4nd0m' res = redirect: sinon.spy() next = sinon.spy() authorize req, res, next done() after -> AuthorizationCode.insert.restore() it 'should set default max_age if none is provided', -> AuthorizationCode.insert.should.have.been.calledWith sinon.match({ max_age: undefined }) it 'should redirect to the redirect_uri', -> res.redirect.should.have.been.calledWith sinon.match( req.connectParams.redirect_uri ) it 'should provide a query string', -> res.redirect.should.have.been.calledWith sinon.match('?') it 'should provide authorization code', -> res.redirect.should.have.been.calledWith sinon.match 'code=1234' it 'should provide state', -> res.redirect.should.have.been.calledWith sinon.match 'state=r4nd0m' it 'should not provide session_state', -> res.redirect.should.not.have.been.calledWith sinon.match('session_state=') describe 'with consent and "code" response type and "max_age" param', -> before (done) -> sinon.stub(AuthorizationCode, 'insert').callsArgWith(1, null, { code: '1234' }) req = session: {} client: _id: 'uuid1' user: _id: 'uuid2' connectParams: authorize: 'true' response_type: 'code' redirect_uri: 'https://host/callback' state: 'r4nd0m' max_age: 1000 res = redirect: sinon.spy() next = sinon.spy() authorize req, res, next done() after -> AuthorizationCode.insert.restore() it 'should set max_age from params', -> AuthorizationCode.insert.should.have.been.calledWith sinon.match({ max_age: req.connectParams.max_age }) describe 'with consent and "code" response type and client "default_max_age"', -> before (done) -> sinon.stub(AuthorizationCode, 'insert').callsArgWith(1, null, { code: '1234' }) req = session: {} client: _id: 'uuid1' default_max_age: 2000 user: _id: 'uuid2' connectParams: authorize: 'true' response_type: 'code' redirect_uri: 'https://host/callback' state: 'r4nd0m' res = redirect: sinon.spy() next = sinon.spy() authorize req, res, next done() after -> AuthorizationCode.insert.restore() it 'should set max_age from client default_max_age', -> AuthorizationCode.insert.should.have.been.calledWith sinon.match({ max_age: req.client.default_max_age }) describe 'with consent and "code token" response type', -> before (done) -> sinon.stub(AuthorizationCode, 'insert').callsArgWith(1, null, { code: '1234' }) response = AccessToken.initialize().project('issue') sinon.stub(AccessToken, 'issue').callsArgWith(1, null, response) req = session: {} client: _id: 'uuid1' user: _id: 'uuid2' connectParams: authorize: 'true' response_type: 'code token' redirect_uri: 'https://host/callback' scope: 'openid profile' state: 'r4nd0m' res = redirect: sinon.spy() next = sinon.spy() authorize req, res, next done() after -> AuthorizationCode.insert.restore() AccessToken.issue.restore() it 'should redirect to the redirect_uri', -> res.redirect.should.have.been.calledWith sinon.match( req.connectParams.redirect_uri ) it 'should provide a uri fragment', -> res.redirect.should.have.been.calledWith sinon.match('#') it 'should provide authorization code', -> res.redirect.should.have.been.calledWith sinon.match 'code=1234' it 'should provide access_token', -> res.redirect.should.have.been.calledWith sinon.match('access_token=') it 'should provide token_type', -> res.redirect.should.have.been.calledWith sinon.match('token_type=Bearer') it 'should provide expires_in', -> res.redirect.should.have.been.calledWith sinon.match('expires_in=3600') it 'should not provide id_token', -> res.redirect.should.not.have.been.calledWith sinon.match('id_token=') it 'should provide state', -> res.redirect.should.have.been.calledWith sinon.match req.connectParams.state it 'should provide session_state', -> res.redirect.should.have.been.calledWith sinon.match('session_state=') describe 'with consent and "code id_token" response type', -> before (done) -> sinon.stub(AuthorizationCode, 'insert').callsArgWith(1, null, { code: '1234' }) sinon.spy(IDToken.prototype, 'initializePayload') req = session: amr: ['sms', 'otp'] client: _id: 'uuid1' user: _id: 'uuid2' connectParams: authorize: 'true' response_type: 'code id_token' redirect_uri: 'https://host/callback' state: 'r4nd0m' res = redirect: sinon.spy() next = sinon.spy() authorize req, res, next done() after -> AuthorizationCode.insert.restore() IDToken.prototype.initializePayload.restore() it 'should set default max_age if none is provided', -> AuthorizationCode.insert.should.have.been.calledWith sinon.match({ max_age: undefined }) it 'should redirect to the redirect_uri', -> res.redirect.should.have.been.calledWith sinon.match( req.connectParams.redirect_uri ) it 'should provide a uri fragment', -> res.redirect.should.have.been.calledWith sinon.match('#') it 'should provide authorization code', -> res.redirect.should.have.been.calledWith sinon.match 'code=1234' it 'should provide id_token', -> res.redirect.should.have.been.calledWith sinon.match('id_token=') it 'should not provide access_token', -> res.redirect.should.not.have.been.calledWith sinon.match('access_token=') it 'should provide state', -> res.redirect.should.have.been.calledWith sinon.match 'state=r4nd0m' it 'should provide session_state', -> res.redirect.should.have.been.calledWith sinon.match('session_state=') it 'should include `amr` claim in id_token', -> IDToken.prototype.initializePayload.should.have.been.calledWith( sinon.match amr: req.session.amr ) describe 'with consent and "id_token token" response type', -> before (done) -> response = AccessToken.initialize().project('issue') sinon.stub(AccessToken, 'issue').callsArgWith(1, null, response) sinon.spy(IDToken.prototype, 'initializePayload') req = session: amr: ['otp'] client: _id: 'uuid1' user: _id: 'uuid2' connectParams: authorize: 'true' response_type: 'id_token token' redirect_uri: 'https://host/callback' nonce: 'n0nc3' state: 'r4nd0m' res = redirect: sinon.spy() next = sinon.spy() authorize req, res, next done() after -> AccessToken.issue.restore() IDToken.prototype.initializePayload.restore() it 'should redirect to the redirect_uri', -> res.redirect.should.have.been.calledWith sinon.match( req.connectParams.redirect_uri ) it 'should provide a uri fragment', -> res.redirect.should.have.been.calledWith sinon.match('#') it 'should provide access_token', -> res.redirect.should.have.been.calledWith sinon.match('access_token=') it 'should provide token_type', -> res.redirect.should.have.been.calledWith sinon.match('token_type=Bearer') it 'should provide expires_in', -> res.redirect.should.have.been.calledWith sinon.match('expires_in=3600') it 'should provide id_token', -> res.redirect.should.have.been.calledWith sinon.match('id_token=') it 'should provide state', -> res.redirect.should.have.been.calledWith sinon.match req.connectParams.state it 'should provide session_state', -> res.redirect.should.have.been.calledWith sinon.match('session_state=') it 'should include `amr` claim in id_token', -> IDToken.prototype.initializePayload.should.have.been.calledWith( sinon.match amr: req.session.amr ) describe 'with consent and "code id_token token" response type', -> before (done) -> sinon.stub(AuthorizationCode, 'insert').callsArgWith(1, null, { code: '1234' }) response = AccessToken.initialize().project('issue') sinon.stub(AccessToken, 'issue').callsArgWith(1, null, response) sinon.spy(IDToken.prototype, 'initializePayload') req = session: amr: ['pwd'] client: _id: 'uuid1' user: _id: 'uuid2' connectParams: authorize: 'true' response_type: 'code id_token token' redirect_uri: 'https://host/callback' scope: 'openid profile' state: 'r4nd0m' res = redirect: sinon.spy() next = sinon.spy() authorize req, res, next done() after -> AuthorizationCode.insert.restore() AccessToken.issue.restore() IDToken.prototype.initializePayload.restore() it 'should redirect to the redirect_uri', -> res.redirect.should.have.been.calledWith sinon.match( req.connectParams.redirect_uri ) it 'should provide a uri fragment', -> res.redirect.should.have.been.calledWith sinon.match('#') it 'should provide authorization code', -> res.redirect.should.have.been.calledWith sinon.match 'code=1234' it 'should provide access_token', -> res.redirect.should.have.been.calledWith sinon.match('access_token=') it 'should provide token_type', -> res.redirect.should.have.been.calledWith sinon.match('token_type=Bearer') it 'should provide expires_in', -> res.redirect.should.have.been.calledWith sinon.match('expires_in=3600') it 'should provide id_token', -> res.redirect.should.have.been.calledWith sinon.match('id_token=') it 'should provide state', -> res.redirect.should.have.been.calledWith sinon.match req.connectParams.state it 'should provide session_state', -> res.redirect.should.have.been.calledWith sinon.match('session_state=') it 'should include `amr` claim in id_token', -> IDToken.prototype.initializePayload.should.have.been.calledWith( sinon.match amr: req.session.amr ) describe 'with consent and "none" response type', -> before (done) -> sinon.stub(AuthorizationCode, 'insert').callsArgWith(1, null, { code: '1234' }) req = session: {} client: _id: 'uuid1' user: _id: 'uuid2' connectParams: authorize: 'true' response_type: 'none' redirect_uri: 'https://host/callback' state: 'r4nd0m' res = redirect: sinon.spy() next = sinon.spy() authorize req, res, next done() after -> AuthorizationCode.insert.restore() it 'should redirect to the redirect_uri', -> res.redirect.should.have.been.calledWith sinon.match( req.connectParams.redirect_uri ) it 'should provide a query string', -> res.redirect.should.have.been.calledWith sinon.match('?') it 'should not provide authorization code', -> res.redirect.should.not.have.been.calledWith sinon.match 'code=1234' it 'should provide state', -> res.redirect.should.have.been.calledWith sinon.match 'state=r4nd0m' it 'should not provide session_state', -> res.redirect.should.not.have.been.calledWith sinon.match('session_state=') describe 'with consent and response mode param', -> before (done) -> response = AccessToken.initialize().project('issue') sinon.stub(AccessToken, 'issue').callsArgWith(1, null, response) req = session: {} client: _id: 'uuid1' user: _id: 'uuid2' connectParams: authorize: 'true' response_type: 'id_token token' response_mode: 'query' redirect_uri: 'https://host/callback' nonce: 'n0nc3' state: 'r4nd0m' res = redirect: sinon.spy() next = sinon.spy() authorize req, res, next done() after -> AccessToken.issue.restore() it 'should redirect to the redirect_uri', -> res.redirect.should.have.been.calledWith sinon.match( req.connectParams.redirect_uri ) it 'should provide a query string', -> res.redirect.should.have.been.calledWith sinon.match('?') describe 'without consent', -> before (done) -> req = client: _id: 'uuid1' user: _id: 'uuid2' connectParams: response_type: 'id_token token' redirect_uri: 'https://host/callback' nonce: 'n0nc3' state: 'r4nd0m' res = redirect: sinon.spy() next = sinon.spy() authorize req, res, next done() it 'should redirect to the redirect_uri', -> res.redirect.should.have.been.calledWith sinon.match( req.connectParams.redirect_uri ) it 'should provide an "access_denied" error', -> res.redirect.should.have.been.calledWith sinon.match('error=access_denied')