Skip to content

Commit

Permalink
Merge 14099e3 into eb07abb
Browse files Browse the repository at this point in the history
  • Loading branch information
huangjoyce3 committed Sep 26, 2019
2 parents eb07abb + 14099e3 commit 72f7d08
Show file tree
Hide file tree
Showing 14 changed files with 415 additions and 163 deletions.
117 changes: 98 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/a30e7499a5234d3494508b7050975beb)](https://www.codacy.com/app/kajabfab/appid-clientsdk-js?utm_source=github.com&utm_medium=referral&utm_content=ibm-cloud-security/appid-clientsdk-js&utm_campaign=Badge_Grade)

# appid-clientsdk-js
Client-side javascript SDK for the IBM Cloud App ID service
Client-side javascript SDK for the IBM Cloud App ID service.

To run locally, first build the project:
```
npm run build
### Table of Contents

- [Installation][1]
- [Getting Started][2]
- [API Reference][3]
- [init][4]
- [signin][5]
- [silentSignin][6]
- [getUserInfo][7]
## Installation
Using npm
```javascript
npm install ibmcloud-appid-js
```

Start the sample app
From the CDN:
```html
<script src="""></script>
```
cd sample
node server.js
Or, use the minified files in this repo:
```html
<script type='text/javascript' src="dist/appid.js"></script>
```
## Getting Started
A simple sample application can be found in the `sample` folder in this repo.
If you want to use our SDK in your existing application, load the script using `script` tags.
```
<script type='text/javascript' src="dist/appid.js"></script>
```

You will need an [IBM Cloud App ID](https://www.ibm.com/cloud/app-id) instance with a `singlepageapp` application created.
Use the `clientId` and `discoveryEndpoint` from the application credentials to initialize the `AppID` instance.
```javascript
Expand All @@ -31,12 +40,82 @@ await appID.init({
discoveryEndpoint: '<WELL_KNOWN_ENDPOINT>'
});
```

## Using Sign In with Popup
```html
<button id="login" class="button">Login</button>
```
The `signinWithPopup` function will trigger a login widget and return the full access and ID tokens along with its payload.
Using the signin() in your app to start authentication:
```javascript
const tokens = await appID.signinWithPopup();
document.getElementById('login').addEventListener('click', async () => {
try {
const tokens = await appID.signin();
} catch (e) {
...
}
});
```
## API Reference
## init
Initialize AppID
#### Parameters
- `clientId` **[string][9]** The clientId from the singlepageapp application credentials.
- `discoveryEndpoint` **[string][9]** The discoveryEndpoint from the singlepageapp application credentials.
- `popup` **[Object][8]** (optional) The popup configuration.
- Throws **AppIDError** For missing required params.
- Throws **RequestError** Any errors during a HTTP request.
Returns **[Promise][10]**
## signin
This will open a login widget in a popup which will prompt the user to enter their credentials.
After a successful login, the popup will close and tokens are returned.
- Throws **AppIDError** AppIDError "Popup closed" - The user closed the popup before authentication was completed.
- Throws **TokenError** Any token validation error.
- Throws **OAuthError** Any errors from the server. e.g. {error: 'server_error', description: ''}
- Throws **RequestError** Any errors during a HTTP request.
Returns **[Promise][10]** The tokens of the authenticated user or an error.
e.g. {accessToken: 'eyg...', accessTokenPayload: { iss: 'https...' }, idToken: 'eyg...', idTokenPayload: { email: 'example@gmail.com' }}
## silentSignin
Silent sign in will attempt to authenticate the user in a hidden iframe.
Sign in will be successful only if there is a Cloud Directory SSO token in the browser.
You will need to enable SSO on the App ID dashboard.
Possible errors include:
User not signed in - there is no Cloud Directory SSO token
- Throws **OAuthError** Any errors from the server. e.g. {error: 'access_denied', description: 'User not signed in'}
- Throws **AppIDError** "Silent sign-in timed out" - The iframe will close after 5 seconds if authentication could not be completed.
- Throws **TokenError** Any token validation error.
- Throws **RequestError** Any errors during a HTTP request.
Returns **[Promise][10]** The tokens of the authenticated user.
e.g. {accessToken: 'eyg...', accessTokenPayload: { iss: 'https...' }, idToken: 'eyg...', idTokenPayload: { email: 'example@gmail.com' }}
## getUserInfo
This method will made a GET request to the user info endpoint using the access token of the authenticated user.
### Parameters
- `accessToken` **[string][9]** The App ID access token of the user
- Throws **AppIDError** "Access token must be a string" - Invalid access token.
- Throws **RequestError** Any errors during a HTTP request.
Returns **[Promise][10]** The user information for the authenticated user. e.g. {sub: '', email: ''}
[1]: #installation
[2]: #getting-started
[3]: #api-reference
[4]: #init
[5]: #signin
[6]: #silentsignin
[7]: #getuserinfo
[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
12 changes: 6 additions & 6 deletions dist/appid.min.js

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions dist/appid.umd.min.js

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"scripts": {
"build": "webpack",
"test": "mocha",
"coverage": "nyc --reporter=lcov mocha"
"coverage": "nyc --reporter=lcov mocha",
"docs": "documentation build src/index.js -f md"
},
"repository": {
"type": "git",
Expand All @@ -20,7 +21,8 @@
"exclude": [
"**/PopupController.js",
"**/IFrameController.js",
"**/OpenIDConfigurationResource.js"
"**/OpenIDConfigurationResource.js",
"**/constants.js"
]
},
"dependencies": {
Expand Down
8 changes: 4 additions & 4 deletions sample/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
<script type='text/javascript' src="appid.min.js"></script>
<script>
function showError(e) {
console.error(e);
document.getElementById('error').textContent = e;
document.getElementById('login').setAttribute('class', 'button');
console.error(e);
document.getElementById('error').textContent = e;
document.getElementById('login').setAttribute('class', 'button');
}

(async function () {
Expand All @@ -57,7 +57,7 @@
document.getElementById('error').textContent = '';

try {
const tokens = await appID.signinWithPopup();
const tokens = await appID.signin();
let userInfo = await appID.getUserInfo(tokens.accessToken);
let decodeIDToken = tokens.idTokenPayload;
document.getElementById('welcome').textContent = 'Hello, ' + decodeIDToken.name;
Expand Down
6 changes: 3 additions & 3 deletions src/PopupController.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ class PopupController {
this.window = w;
};

open() {
const h = 700;
const w = 400;
open(popup) {
const h = popup.height;
const w = popup.width;
const left = (screen.width - w) / 2;
const top = (screen.height - h) / 2;
this.popup = this.window.open('', 'popup', `left=${left},top=${top},width=${w},height=${h},resizable,scrollbars=yes,status=1`);
Expand Down
2 changes: 2 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ module.exports = {
INVALID_TOKEN: 'Invalid token',
MISSING_PUBLIC_KEY: 'Cannot find public key',
INVALID_ACCESS_TOKEN: 'Access token must be a string',
MISSING_CLIENT_ID: 'Missing client ID',
MISSING_DISCOVERY_ENDPOINT: 'Missing discovery endpoint',
RESPONSE_TYPE: 'code',
RESPONSE_MODE: 'web_message',
PROMPT: 'none',
Expand Down
8 changes: 1 addition & 7 deletions src/errors/AppIDError.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
class AppIDError extends Error {
constructor({error, description}) {
super(description || error);
this.error = error;
this.description = description;
}
}
class AppIDError extends Error {}
module.exports = AppIDError;
9 changes: 9 additions & 0 deletions src/errors/OAuthError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class OAuthError extends Error {
// See https://tools.ietf.org/html/rfc6749#section-4.1.2.1 for the possible error messages
constructor({error, description}) {
super(description || error);
this.error = error;
this.description = description;
}
}
module.exports = OAuthError;
Loading

0 comments on commit 72f7d08

Please sign in to comment.