Skip to content

Commit 2228b67

Browse files
jevakalliokadikraman
authored andcommitted
Support manual service configuration (#52)
* First naive stab at passing serviceConfiguration manually * Naive implementation of manually configured refreshing + client secret support * Add support for revocation with manual service configuration * Make clientSecret a native method parameter instead of bundling in additionalProperties * Initial implementation of manual configuration for ios * Accept clientSecret as a parameter to authorize/refresh * Update tests * Add typescript definitions * Update readme * Add support for registrationEndpoint, refactor * Refactor and clean up * Fix discovered revocation endpoint url * Fix revocation endpoint validation * Example of using serviceConfiguration + clientSecret with Uber * Update tests for error messages * Comment out (but intentionally leave in) manual serviceConfiguration example for easy testing * Fix typo in readme * Better error messages * Remove autogenerated comments * Fix typo in error message * Fix typos in README * Fix typos in error messages
1 parent c9c70cf commit 2228b67

File tree

8 files changed

+686
-285
lines changed

8 files changed

+686
-285
lines changed

Example/App.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ const config = {
1919
redirectUrl: 'io.identityserver.demo:/oauthredirect',
2020
additionalParameters: {},
2121
scopes: ['openid', 'profile', 'email', 'offline_access']
22+
23+
// serviceConfiguration: {
24+
// authorizationEndpoint: 'https://demo.identityserver.io/connect/authorize',
25+
// tokenEndpoint: 'https://demo.identityserver.io/connect/token',
26+
// revocationEndpoint: 'https://demo.identityserver.io/connect/revoke'
27+
// }
2228
};
2329

2430
export default class App extends Component<{}, State> {
@@ -41,7 +47,7 @@ export default class App extends Component<{}, State> {
4147
authorize = async () => {
4248
try {
4349
const authState = await authorize(config);
44-
50+
4551
this.animateState(
4652
{
4753
hasLoggedInOnce: true,

README.md

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,20 @@ const result = await authorize(config);
7272
This is your configuration object for the client. The config is passed into each of the methods
7373
with optional overrides.
7474

75-
* **issuer** - (`string`) _REQUIRED_ the url of the auth server
75+
* **issuer** - (`string`) base URI of the authentication server. If no `serviceConfiguration` (below) is provided, issuer is a mandatory field, so that the configuration can be fetched from the issuer's [OIDC discovery endpoint](https://openid.net/specs/openid-connect-discovery-1_0.html).
76+
* **serviceConfiguration** - (`object`) you may manually configure token exchange endpoints in cases where the issuer does not support the OIDC discovery protocol, or simply to avoid an additional round trip to fetch the configuration. If no `issuer` (above) is provided, the service configuration is mandatory.
77+
* **authorizationEndpoint** - (`string`) _REQUIRED_ fully formed url to the OAuth authorization endpoint
78+
* **tokenEndpoint** - (`string`) _REQUIRED_ fully formed url to the OAuth token exchange endpoint
79+
* **revocationEndpoint** - (`string`) fully formed url to the OAuth token revocation endpoint. If you want to be able to revoke a token and no `issuer` is specified, this field is mandatory.
80+
* **registrationEndpoint** - (`string`) fully formed url to your OAuth/OpenID Connect registration endpoint. Only necessary for servers that require client registration.
7681
* **clientId** - (`string`) _REQUIRED_ your client id on the auth server
82+
* **clientSecret** - (`string`) client secret to pass to token exchange requests. :warning: Read more about [client secrets](#note-about-client-secrets)
7783
* **redirectUrl** - (`string`) _REQUIRED_ the url that links back to your app with the auth code
7884
* **scopes** - (`array<string>`) _REQUIRED_ the scopes for your token, e.g. `['email', 'offline_access']`
7985
* **additionalParameters** - (`object`) additional parameters that will be passed in the authorization request.
8086
Must be string values! E.g. setting `additionalParameters: { hello: 'world', foo: 'bar' }` would add
8187
`hello=world&foo=bar` to the authorization request.
82-
* :warning: **dangerouslyAllowInsecureHttpRequests** - (`boolean`) _ANDROID_ whether to allow requests over plain HTTP or with self-signed SSL certificates. Can be useful for testing against local server, _should not be used in production._ This setting has no effect on iOS; to enable insecure HTTP requests, add a [NSExceptionAllowsInsecureHTTPLoads exception](https://cocoacasts.com/how-to-add-app-transport-security-exception-domains) to your App Transport Security settings.
88+
* **dangerouslyAllowInsecureHttpRequests** - (`boolean`) _ANDROID_ whether to allow requests over plain HTTP or with self-signed SSL certificates. :warning: Can be useful for testing against local server, _should not be used in production._ This setting has no effect on iOS; to enable insecure HTTP requests, add a [NSExceptionAllowsInsecureHTTPLoads exception](https://cocoacasts.com/how-to-add-app-transport-security-exception-domains) to your App Transport Security settings.
8389

8490
#### result
8591

@@ -353,6 +359,14 @@ try {
353359

354360
See example configurations for different providers below.
355361

362+
### Note about client secrets
363+
364+
Some authentication providers, including examples cited below, require you to provide a client secret. The authors of the AppAuth library
365+
366+
> [strongly recommend](https://github.com/openid/AppAuth-Android#utilizing-client-secrets-dangerous) you avoid using static client secrets in your native applications whenever possible. Client secrets derived via a dynamic client registration are safe to use, but static client secrets can be easily extracted from your apps and allow others to impersonate your app and steal user data. If client secrets must be used by the OAuth2 provider you are integrating with, we strongly recommend performing the code exchange step on your backend, where the client secret can be kept hidden.
367+
368+
Having said this, in some cases using client secrets is unavoidable. In these cases, a `clientSecret` parameter can be provided to `authorize`/`refresh` calls when performing a token request.
369+
356370
### Identity Server 4
357371

358372
This library supports authenticating for Identity Server 4 out of the box. Some quirks:
@@ -467,6 +481,42 @@ const refreshedState = await refresh(config, {
467481
});
468482
```
469483

484+
### Uber
485+
486+
Uber provides an OAuth 2.0 endpoint for logging in with a Uber user's credentials. You'll need to first [create an Uber OAuth application here](https://developer.uber.com/docs/riders/guides/authentication/introduction).
487+
488+
Please note:
489+
490+
* Uber does not provide a OIDC discovery endpoint, so `serviceConfiguration` is used instead.
491+
* Uber OAuth requires a [client secret](#note-about-client-secrets).
492+
493+
```js
494+
const config = {
495+
clientId: 'your-client-id-generated-by-uber',
496+
clientSecret: 'your-client-secret-generated-by-uber',
497+
redirectUrl: 'com.whatever.url.you.configured.in.uber.oauth://redirect', //note: path is required
498+
scopes: ['profile', 'delivery'], // whatever scopes you configured in Uber OAuth portal
499+
serviceConfiguration: {
500+
authorizationEndpoint: 'https://login.uber.com/oauth/v2/authorize',
501+
tokenEndpoint: 'https://login.uber.com/oauth/v2/token',
502+
revocationEndpoint: 'https://login.uber.com/oauth/v2/revoke'
503+
}
504+
};
505+
506+
// Log in to get an authentication token
507+
const authState = await authorize(config);
508+
509+
// Refresh token
510+
const refreshedState = await refresh(config, {
511+
refreshToken: authState.refreshToken,
512+
});
513+
514+
// Revoke token
515+
await revoke(config, {
516+
tokenToRevoke: refreshedState.refreshToken
517+
});
518+
```
519+
470520
## Contributors
471521

472522
Thanks goes to these wonderful people

0 commit comments

Comments
 (0)