@solid/oidc-auth-manager
Version:
An OpenID Connect (OIDC) authentication manager (OP, RP and RS) for decentralized peer-to-peer authentication
247 lines (201 loc) • 7.85 kB
JavaScript
'use strict'
const chai = require('chai')
const sinon = require('sinon')
const dirtyChai = require('dirty-chai')
chai.use(dirtyChai)
const sinonChai = require('sinon-chai')
chai.use(sinonChai)
const expect = chai.expect
const HttpMocks = require('node-mocks-http')
const SelectProviderRequest = require('../../src/handlers/select-provider-request')
describe('SelectProviderRequest', () => {
describe('normalizeWebId()', () => {
it('should prepend https:// if one is missing', () => {
const result = SelectProviderRequest.normalizeUri('localhost:8443')
expect(result).to.equal('https://localhost:8443')
})
it('should return null if given a null uri', () => {
const result = SelectProviderRequest.normalizeUri(null)
expect(result).to.be.null()
})
it('should return a valid uri unchanged', () => {
const result = SelectProviderRequest.normalizeUri('https://alice.example.com')
expect(result).to.equal('https://alice.example.com')
})
})
describe('validate()', () => {
it('should throw a 500 error if no oidcManager was initialized', (done) => {
const aliceWebId = 'https://alice.example.com'
const options = {
webId: aliceWebId
}
const request = new SelectProviderRequest(options)
try {
request.validate()
} catch (error) {
expect(error.statusCode).to.equal(500)
done()
}
})
it('should throw a 400 error if no webid is submitted', (done) => {
const options = {
oidcManager: {}
}
const request = new SelectProviderRequest(options)
try {
request.validate()
} catch (error) {
expect(error.statusCode).to.equal(400)
done()
}
})
it('should throw a 400 if an invalid webid was submitted', (done) => {
const options = {
webId: 'invalidWebId',
oidcManager: {}
}
const request = new SelectProviderRequest(options)
try {
request.validate()
} catch (error) {
expect(error.statusCode).to.equal(400)
done()
}
})
})
describe('fromParams()', () => {
const res = HttpMocks.createResponse()
const serverUri = 'https://example.com'
// 'https%3A%2F%2Foriginal.com%2Fpath%23hash'
const returnToUrl = encodeURIComponent('https://original.com/path#hash')
it('should initialize a SelectProviderRequest instance', () => {
const aliceWebId = 'https://alice.example.com'
const oidcManager = {}
const session = {}
const req = {
session,
body: { webid: aliceWebId },
query: { returnToUrl },
app: { locals: { oidc: oidcManager, host: { serverUri } } }
}
const request = SelectProviderRequest.fromParams(req, res)
expect(request.webId).to.equal(aliceWebId)
expect(request.response).to.equal(res)
expect(request.oidcManager).to.equal(oidcManager)
expect(request.session).to.equal(session)
expect(request.serverUri).to.equal(serverUri)
expect(request.returnToUrl).to.equal(returnToUrl)
})
it('should attempt to normalize an invalid webid uri', () => {
const oidcManager = {}
const session = {}
const req = {
session,
body: { webid: 'alice.example.com' },
app: { locals: { oidc: oidcManager, host: { serverUri } } }
}
const request = SelectProviderRequest.fromParams(req, res)
expect(request.webId).to.equal('https://alice.example.com')
})
})
describe('static get()', () => {
it('creates a request instance and renders the select provider view', () => {
const serverUri = 'https://example.com'
const req = {
app: { locals: { oidc: {}, host: { serverUri } } }
}
const res = {}
res.render = sinon.stub()
SelectProviderRequest.get(req, res)
expect(res.render).to.have.been.calledWith('auth/select-provider', { serverUri })
})
})
describe('saveReturnToUrl()', () => {
it('should save the returnToUrl in session', () => {
const response = HttpMocks.createResponse()
const session = {}
const returnToUrl = encodeURIComponent('https://example.com/path#hash')
const request = new SelectProviderRequest({ response, session, returnToUrl })
request.saveReturnToUrl()
expect(request.session.returnToUrl).to.equal(returnToUrl)
})
})
describe('selectProvider()', () => {
it('should fetch the provider uri and redirect user to its /authorize endpoint', () => {
const webId = 'https://example.com/#me'
const clientStore = {}
const authUrl = 'https://example.com/authorize?client_id=1234'
clientStore.authUrlForIssuer = sinon.stub().resolves(authUrl)
const oidcManager = {
clients: clientStore,
debug: console.log.bind(console)
}
const response = HttpMocks.createResponse()
const session = {}
const request = new SelectProviderRequest({ webId, oidcManager, response, session })
const providerUri = 'https://example.com'
request.preferredProviderUrl = sinon.stub().resolves(providerUri)
return request.selectProvider()
.then(() => {
expect(request.preferredProviderUrl).to.have.been.called()
expect(clientStore.authUrlForIssuer).to.have.been.calledWith(providerUri, session)
expect(request.response._getRedirectUrl()).to.equal(authUrl)
})
})
})
describe('error()', () => {
it('should render select provider form with appropriate error message', () => {
const response = HttpMocks.createResponse()
response.render = sinon.stub()
const request = new SelectProviderRequest({ response })
const error = new Error('error message')
error.statusCode = 404
request.error(error)
expect(request.response.statusCode).to.equal(404)
expect(response.render).to
.have.been.calledWith('auth/select-provider', { error: 'error message' })
})
})
describe('handlePost()', () => {
it('should validate the request and select the provider', () => {
const request = new SelectProviderRequest({})
request.validate = sinon.stub().resolves()
request.selectProvider = sinon.stub().resolves()
request.saveReturnToUrl = sinon.stub()
return SelectProviderRequest.handlePost(request)
.then(() => {
expect(request.validate).to.have.been.called()
expect(request.selectProvider).to.have.been.called()
expect(request.saveReturnToUrl).to.have.been.called()
})
})
it('should route any errors to the request.error() handler', done => {
const request = new SelectProviderRequest({})
const thrownError = new Error('validation error')
request.validate = sinon.stub().rejects(thrownError)
request.error = sinon.stub()
SelectProviderRequest.handlePost(request)
.then(() => {
expect(request.error).to.have.been.calledWith(thrownError)
done()
})
})
})
describe('post()', () => {
const SelectProviderRequest = require('../../src/handlers/select-provider-request')
it('should create a request instance and invoke handlePost()', () => {
const req = HttpMocks.createRequest()
const res = HttpMocks.createResponse()
const request = new SelectProviderRequest({})
SelectProviderRequest.fromParams = sinon.stub().returns(request)
SelectProviderRequest.handlePost = sinon.stub().resolves()
return SelectProviderRequest.post(req, res)
.then(() => {
expect(SelectProviderRequest.fromParams)
.to.have.been.calledWith(req, res)
expect(SelectProviderRequest.handlePost)
.to.have.been.calledWith(request)
})
})
})
})