Skip to content

Commit

Permalink
feat(redirect): add support for login_hint
Browse files Browse the repository at this point in the history
This allows "hinting" a specific identity provider to the authentication
server.

Example: Upon opening the app at http://my-app.com?login_hint=myidp
will automatically use the specified IDP (in this case "myidp") if not logged in.

This also adds a new config option "loginHintName" that allows using a
different parameter name (e.g. Keycloak's `kc_idp_hint`).
  • Loading branch information
czosel authored and kaldras committed Jul 24, 2019
1 parent c072440 commit 9074063
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 15 deletions.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# ember-simple-auth-oidc

[![npm version](https://badge.fury.io/js/ember-simple-auth-oidc.svg)](https://www.npmjs.com/package/ember-simple-auth-oidc)
[![Build Status](https://travis-ci.com/adfinis-sygroup/ember-simple-auth-oidc.svg?branch=master)](https://travis-ci.com/adfinis-sygroup/ember-simple-auth-oidc)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)


A [Ember Simple Auth](http://ember-simple-auth.com) addon which implements the
OpenID Connect [Authorization Code Flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth).

Expand Down Expand Up @@ -82,12 +82,12 @@ module.exports = function(environment) {
clientId: "test",
authEndpoint: "/authorize",
tokenEndpoint: "/token",
userinfoEndpoint: "/userinfo",
userinfoEndpoint: "/userinfo"
}
// ...
}
};
return ENV;
}
};
```

Here is a complete list of all possible config options:
Expand Down Expand Up @@ -135,6 +135,10 @@ Default is `Authorization`.
**authPrefix** \<String\> (optional)
Prefix of the authentication token. Default is `Bearer`.

**loginHintName** \<String\> (optional)
Name of the `login_hint` query paramter which is being forwarded to the authorization server if it is present.
This option allows overriding the default name `login_hint`.

## Contributing

### Installation
Expand Down
22 changes: 15 additions & 7 deletions addon/mixins/oidc-authentication-route-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import getAbsoluteUrl from "ember-simple-auth-oidc/utils/absoluteUrl";
import v4 from "uuid/v4";
import { assert } from "@ember/debug";

const { host, clientId, authEndpoint, scope } = config;
const { host, clientId, authEndpoint, scope, loginHintName } = config;

export default Mixin.create(UnauthenticatedRouteMixin, {
session: service(),
Expand Down Expand Up @@ -56,15 +56,18 @@ export default Mixin.create(UnauthenticatedRouteMixin, {
);
}

const { code, state } = transition.to
const queryParams = transition.to
? transition.to.queryParams
: transition.queryParams;

if (code) {
return await this._handleCallbackRequest(code, state);
if (queryParams.code) {
return await this._handleCallbackRequest(
queryParams.code,
queryParams.state
);
}

return this._handleRedirectRequest();
return this._handleRedirectRequest(queryParams);
},

/**
Expand Down Expand Up @@ -113,7 +116,7 @@ export default Mixin.create(UnauthenticatedRouteMixin, {
* match this state, otherwise the authentication will fail to prevent from
* CSRF attacks.
*/
_handleRedirectRequest() {
_handleRedirectRequest(queryParams) {
let state = v4();

this.session.set("data.state", state);
Expand All @@ -126,13 +129,18 @@ export default Mixin.create(UnauthenticatedRouteMixin, {
this.session.get("attemptedTransition.intent.url")
);

// forward `login_hint` query param if present
const key = loginHintName || "login_hint";
const forwarded = queryParams[key] ? `&${key}=${queryParams[key]}` : "";

this._redirectToUrl(
`${getAbsoluteUrl(host)}${authEndpoint}?` +
`client_id=${clientId}&` +
`redirect_uri=${this.redirectUri}&` +
`response_type=code&` +
`state=${state}&` +
`scope=${scope}`
`scope=${scope}` +
forwarded
);
}
});
3 changes: 2 additions & 1 deletion tests/dummy/config/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ module.exports = function(environment) {
tokenEndpoint: "/protocol/openid-connect/token",
endSessionEndpoint: "/protocol/openid-connect/logout",
userinfoEndpoint: "/protocol/openid-connect/userinfo",
afterLogoutUri: "http://localhost:4200"
afterLogoutUri: "http://localhost:4200",
loginHintName: "custom_login_hint"
},

EmberENV: {
Expand Down
28 changes: 25 additions & 3 deletions tests/unit/mixins/oidc-authentication-route-mixin-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ module("Unit | Mixin | oidc-authentication-route-mixin", function(hooks) {
redirectUri: "test",
session: EmberObject.create({ data: { authenticated: {} } }),
_redirectToUrl(url) {
assert.ok(new RegExp(authEndpoint).test(url));
assert.ok(url.includes(authEndpoint));

assert.ok(new RegExp(`client_id=${clientId}`).test(url));
assert.ok(new RegExp("redirect_uri=test").test(url));
assert.ok(url.includes(`client_id=${clientId}`));
assert.ok(url.includes("redirect_uri=test"));
}
});

Expand Down Expand Up @@ -117,4 +117,26 @@ module("Unit | Mixin | oidc-authentication-route-mixin", function(hooks) {
Error
);
});

test("it forwards customized login_hint param", function(assert) {
assert.expect(4);

let Route = EmberObject.extend(OIDCAuthenticationRouteMixin);

let subject = Route.create({
redirectUri: "test",
session: EmberObject.create({ data: { authenticated: {} } }),
_redirectToUrl(url) {
assert.ok(url.includes(authEndpoint));

assert.ok(url.includes(`client_id=${clientId}`));
assert.ok(url.includes("redirect_uri=test"));
assert.ok(url.includes("custom_login_hint=my-idp"));
}
});

subject.afterModel(null, {
to: { queryParams: { custom_login_hint: "my-idp" } }
});
});
});

0 comments on commit 9074063

Please sign in to comment.