Skip to content

Commit

Permalink
Fix handling of auth scheme/strategy realms (#4281)
Browse files Browse the repository at this point in the history
* Fix handling of auth scheme/strategy realms. Closes #4218

* Remove whitespace
  • Loading branch information
devinivy committed Sep 14, 2021
1 parent ab40394 commit e639788
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 4 deletions.
2 changes: 1 addition & 1 deletion API.md
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ Registers an authentication scheme where:

- `name` - the scheme name.
- `scheme` - the method implementing the scheme with signature `function(server, options)` where:
- `server` - a reference to the server object the scheme is added to.
- `server` - a reference to the server object the scheme is added to. Each auth strategy is given its own [`server.realm`](#server.realm) whose parent is the realm of the `server` in the call to [`server.auth.strategy()`](#server.auth.strategy()).
- `options` - (optional) the scheme `options` argument passed to
[`server.auth.strategy()`](#server.auth.strategy()) when instantiation a strategy.

Expand Down
16 changes: 15 additions & 1 deletion lib/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ exports = module.exports = internals.Auth = class {
#schemes = {};
#strategies = {};

api = {};
api = {}; // Do not reassign api or settings, as they are referenced in public()
settings = {
default: null // Strategy used as default if route has no auth settings
};
Expand All @@ -29,6 +29,20 @@ exports = module.exports = internals.Auth = class {
this.#core = core;
}

public(server) {

return {
api: this.api,
settings: this.settings,
scheme: this.scheme.bind(this),
strategy: this._strategy.bind(this, server),
default: this.default.bind(this),
test: this.test.bind(this),
verify: this.verify.bind(this),
lookup: this.lookup.bind(this)
};
}

scheme(name, scheme) {

Hoek.assert(name, 'Authentication scheme must have a name');
Expand Down
3 changes: 1 addition & 2 deletions lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ internals.Server = class {
// Public interface

this.app = core.app;
this.auth = this._core.auth;
this.auth.strategy = this.auth._strategy.bind(this.auth, this);
this.auth = core.auth.public(this);
this.decorations = core.decorations.public;
this.cache = internals.cache(this);
this.events = core.events;
Expand Down
41 changes: 41 additions & 0 deletions test/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,47 @@ describe('authentication', () => {

expect(server.auth.api.xyz.x).to.equal(5);
});

it('has its own realm', async () => {

const implementation = function (server) {

return {
authenticate: (_, h) => h.authenticated({ credentials: server.realm })
};
};

const server = Hapi.server();

server.auth.scheme('custom', implementation);
server.auth.strategy('root', 'custom');

let pluginA;

await server.register({
name: 'plugin-a',
register(srv) {

pluginA = srv;

srv.auth.strategy('a', 'custom');
}
});

const handler = (request) => request.auth.credentials;
server.route({ method: 'GET', path: '/a', handler, options: { auth: 'a' } });
server.route({ method: 'GET', path: '/root', handler, options: { auth: 'root' } });

const { result: realm1 } = await server.inject('/a');
expect(realm1.plugin).to.be.undefined();
expect(realm1).to.not.shallow.equal(server.realm);
expect(realm1.parent).to.shallow.equal(pluginA.realm);

const { result: realm2 } = await server.inject('/root');
expect(realm2.plugin).to.be.undefined();
expect(realm2).to.not.shallow.equal(server.realm);
expect(realm2.parent).to.shallow.equal(server.realm);
});
});

describe('default()', () => {
Expand Down

0 comments on commit e639788

Please sign in to comment.