Skip to content

Commit

Permalink
First import
Browse files Browse the repository at this point in the history
  • Loading branch information
biilmann committed May 17, 2016
0 parents commit 8ce4362
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
lib/
node_modules/
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
src/
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Authlify JS Client

This is a JS library for the [Authlify](https://github.com/netlify/authlify) API.

It lets you signup and authenticate users and is a building block for constructing
the UI for signups, password recovery, login and logout.

## Usage

```js
import Authlify from 'authlify-js'

const authlify = new Authlify({
APIUrl: 'https://authlify.netlify.com'
});

authlify.signup(username, email).then(
(response) => console.log("Confirmation email sent"),
(error) => console.log("Error during signup: %o", error.msg)
);

authlify.confirm(token).then(
(user) => console.log("Logged in as %s", user.email),
(error) => console.log("Failed to log in: %o", error)
);

authlify.requestPasswordRecovery(email).then(
(response) => console.log("Recovery email sent"),
(error) => console.log("Error sending recovery mail: %o", error)
);

authlify.recover(token).then(
(user) => console.log("Logged in as %s", user.email),
(error) => console.log("Failed to verify recover token: %o", error)
);

user.update({email: newEmail, password: newPassword}).then(
(user) => console.log("Updated user"),
(error) => console.log("Failed to update user: %o", error)
);

user.jwt().then(
(token) => console.log("Current token: %s", token),
(error) => console.log("Failed to get token: %o", error)
);

user.logout().then(
(response) => console.log("User logged out"),
(error) => console.log("Failed to logout user: %o", error)
);
```
18 changes: 18 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "authlify-js",
"version": "0.1.0",
"description": "Authlify API client for JavaScript",
"main": "lib/index.js",
"scripts": {
"compile": "babel --presets es2015 --plugins syntax-object-rest-spread,transform-object-rest-spread -d lib/ src/",
"prepublish": "npm run compile"
},
"author": "Mathias Biilmann Christensen",
"license": "MIT",
"devDependencies": {
"babel-cli": "^6.8.0",
"babel-plugin-syntax-object-rest-spread": "^6.8.0",
"babel-plugin-transform-object-rest-spread": "^6.8.0",
"babel-preset-es2015": "^6.6.0"
}
}
34 changes: 34 additions & 0 deletions src/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export default class API {
constructor(apiURL) {
this.apiURL = apiURL;
}

headers(headers = {}) {
return {
'Content-Type': 'application/json',
...headers
};
}

parseJsonResponse(response) {
return response.json().then((json) => {
if (!response.ok) {
return Promise.reject(json);
}

return json;
});
}

request(path, options = {}) {
const headers = this.headers(options.headers || {});
return fetch(this.apiURL + path, {...options, headers}).then((response) => {
const contentType = response.headers.get('Content-Type');
if (contentType && contentType.match(/json/)) {
return this.parseJsonResponse(response);
}

return response.text().then((text) => ({data: text}));
});
}
}
49 changes: 49 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import API from './api';
import User from './user';

const HTTPRegexp = /^http:\/\//;

export default class Authlify {
constructor(options = {}) {
if (!options.APIUrl) {
throw("You must specify an APIUrl of your Authlify instance");
}
if (!options.APIUrl.match(HTTPRegexp)) {
console.log('Warning:\n\nDO NOT USE HTTP IN PRODUCTION FOR AUTHLIFY EVER!\nAuthlify REQUIRES HTTPS to work securely.')
}
this.api = new API(options.APIUrl);
}

signup(email, password) {
return this.api.request('/signup', {
method: 'POST',
body: JSON.stringify({email, password})
});
}

confirm(token) {
return this.verify('signup', token);
}

requestPasswordRecovery(email) {
return this.api.request('/recover', {
method: 'POST',
body: JSON.stringify({email})
});
}

recover(token) {
return this.verify('recovery', token);
}

verify(type, token) {
return this.api.request('/verify', {
method: 'POST',
body: JSON.stringify({token, type})
}).then((response) => {
const user = new User(this.api, response);
user.reload();
return user;
});
}
}
61 changes: 61 additions & 0 deletions src/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const ExpiryMargin = 60 * 1000;

export default class User {
constructor(api, tokenResponse) {
const now = new Date();
this.api = api;
this.processTokenResponse(tokenResponse);
}

update(attributes) {
this.request('/user', {
method: 'PUT',
body: JSON.stringify(attributes)
}).then((response) => {
for (var key in response) {
this[key] = response[key];
}
return this;
});
}

jwt() {
if (this.jwt_expiry + ExpiryMargin > new Date().getTime()) {
return this.api.request('/token', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: `grant_type=refresh_token&refresh_token=${this.refreshToken}`
}).then((response) => {
this.processTokenResponse(response);
return this.jwt;
});
}
return Promise.resolve(this.jwt);
}

logout() {
return this.request('/logout', {method: 'POST'});
}

request(path, options) {
return this.jwt().then((token) => this.api.request(path, {
headers: {Authorization: `Bearer ${token}`},
...options
}));
}

reload() {
this.request('/user').then((response) => {
for (var key in response) {
this[key] = response[key];
}
return this;
});
}

processTokenResponse(tokenResponse) {
this.refreshToken = tokenResponse.refresh_token;
this.jwt = tokenResponse.access_token;
this.jwt_expiry = now.setTime(now.getTime() + (tokenResponse.expires_in * 1000)).getTime();
}
}

0 comments on commit 8ce4362

Please sign in to comment.