Skip to content

Commit

Permalink
Oauth authenticate without redirect uri
Browse files Browse the repository at this point in the history
  • Loading branch information
Simona Peneva committed Aug 20, 2018
1 parent dd329f6 commit 246c3f9
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 51 deletions.
25 changes: 19 additions & 6 deletions docs/api-oauth.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
## pCloudSdk.oauth

- This is the API Reference for the `oauth` export. For details how to use them see [Oauth](oauth.md).
- If you want to built yourself a custom Oauth flow see the [pCloud's API Docs](https://docs.pcloud.com/methods/oauth_2.0/index.html).
* This is the API Reference for the `oauth` export. For details how to use them see [Oauth](oauth.md).
* If you want to built yourself a custom Oauth flow see the [pCloud's API Docs](https://docs.pcloud.com/methods/oauth_2.0/index.html).

#### initOauthToken

``` js
```js
initOauthToken({
client_id: string,
redirect_uri: string,
Expand All @@ -14,23 +14,36 @@ initOauthToken({
});
```

You can use following method for Oauth authenticate without redirect uri(see [listfolder example](../examples/listfolder.html)):

#### initOauthPollToken

```js
initOauthPollToken({
client_id: string,
receiveToken: () => void,
onError:() => void
});
```

#### popup()

``` html
```html
// inside redirect_uri window
<script>
pCloudSdk.oauth.popup();
</script>
```


#### getTokenFromCode

``` js
```js
getTokenFromCode(
code: string,
client_id: string,
app_secret: string
): Promise<{ userid, access_token }>
```

- `code` can be received either manually by the user via copy & paste (see [oauth example](../examples/node/token.js)) or by specifying `response_type: "code"` to `initOauthToken`.
* `code` can be received either manually by the user via copy & paste (see [oauth example](../examples/node/token.js)) or by specifying `response_type: "code"` to `initOauthToken`.
31 changes: 23 additions & 8 deletions docs/oauth.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ In order to use pCloud api calls, you first need to acquire a token from the use
* (**Client side only**) Setup a redirect url to which you have access to and can place a static html page.

## Client side flow

Use the following snippet in some user initiated action (click):

``` js
```js
pCloudSdk.oauth.initOauthToken({
client_id: 'YOUR_CLIENT_ID',
redirect_uri: 'YOUR_REDIRECT_URL',
response_type: 'token' | 'code',
client_id: "YOUR_CLIENT_ID",
redirect_uri: "YOUR_REDIRECT_URL",
response_type: "token" | "code",
receiveToken: function(access_token) {
// do something with the token.
}
Expand All @@ -21,22 +22,36 @@ pCloudSdk.oauth.initOauthToken({

This will open a popup window where the user can authorize the usage of your app. After this he will be redirected to the `redirect_uri` page which needs to be a simple html that loads the SDK and runs the following:

``` js
```js
pCloudSdk.oauth.popup();
```

This will ensure that the snippet above will work and the `access_token` will be received. Checkout the [oauth examples](../examples/) for more info.

## Server side flow

For server side applications you would be using a token received from the user via the client side flow and then saved in some kind persistent storage (database or else).

For easing you in using the SDK, you can use the tool provided in the `examples/node` folder of this repo. Enter your application's `client_id` and `app_secret` in `app.json` using the following format:

``` json
```json
{
"client_id": "",
"app_secret":""
"app_secret": ""
}
```

Then run `node examples/node/token.js` and follow the prompts. The process will save the generated `access_token` and the `userid` of the user in the `app.json`. All examples will work afterwards.
Then run `node examples/node/token.js` and follow the prompts. The process will save the generated `access_token` and the `userid` of the user in the `app.json`. All examples will work afterwards.

* (**Client side only with poll request**)
Use the following snippet in some user initiated action (click):

```js
pCloudSdk.oauth.initOauthPollToken({
client_id: "YOUR_CLIENT_ID",
receiveToken: function(access_token) {
// do something with the token.
},
onError: function(err) {}
});
```
61 changes: 42 additions & 19 deletions examples/listfolder.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
<html>

<head>
<title>pCloud SDK: Examples / List folder</title>
<style>
body {
margin: 0;
padding: 20px;
}
#gettoken {
position: fixed;

#gettoken-redirect {
top: 20px;
position: fixed;
right: 20px;
}

#gettoken-poll {
top: 50px;
position: fixed;
right: 20px;
}
</style>
</head>

<body>

<button id="gettoken">Get Token</button>
<button id="gettoken-redirect">Get Token(redirect)</button>
<button id="gettoken-poll">Get Token(poll)</button>

<script type="text/javascript" src="examples/pcloudsdk.js"></script>
<script>
Expand Down Expand Up @@ -85,26 +95,39 @@
return client.listfolder(0).then(children).then(map(name));
}

el('gettoken').addEventListener('click', function(e) {
function receiveTokenCb(token) {
console.log(token);
access_token = token;
client = pCloudSdk.createClient(token);

folderSize(0).then((a) => {
console.log('Size: ', a);
});

folderItems(0).then((a) => {
console.log('Items: ', a);
});
}
// Oauth authenticate with redirect uri
el('gettoken-redirect').addEventListener('click', function (e) {
pCloudSdk.oauth.initOauthToken({
client_id: 'p1WznE2dEPm',
client_id: 'BJpmGFpuj3S',
redirect_uri: 'http://127.0.0.1:8080/oauth.html',
receiveToken: function(token) {
console.log(token);
access_token = token;
client = pCloudSdk.createClient(token);

folderSize(0).then((a) => {
console.log('Size: ', a);
});

folderItems(0).then((a) => {
console.log('Items: ', a);
});
}
receiveToken: receiveTokenCb,
onError: err => console.log(err)
});
}, false);

// Oauth authenticate without redirect uri
el('gettoken-poll').addEventListener('click', function (e) {
pCloudSdk.oauth.initOauthPollToken({
client_id: 'BJpmGFpuj3S',
receiveToken: receiveTokenCb,
onError: err => console.log(err)
});
}, false);

</script>
</body>
</html>

</html>
2 changes: 1 addition & 1 deletion examples/node/download.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const pcloud = require('../../lib');
const pcloud = require('pcloud-sdk-js');
const invariant = require('invariant');
const path = require('path');

Expand Down
2 changes: 1 addition & 1 deletion examples/node/token.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
var prompt = require('prompt');
var fs = require('fs');
var url = require('url');
var oauth = require('../../lib').oauth;
var oauth = require('pcloud-sdk-js').oauth;

if (!appExists()) {
resetAppJson();
Expand Down
2 changes: 1 addition & 1 deletion examples/node/upload.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const pcloud = require('../../lib');
const pcloud = require('pcloud-sdk-js');
const invariant = require('invariant');
const app = require('./app.json');

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

78 changes: 64 additions & 14 deletions src/oauth/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import url from "url";
import invariant from "invariant";
import ApiMethod from "../api/ApiMethod";
import { generateRandomString } from "../utils/functions";

const protocol = "https";
const host = "my.pcloud.com";
Expand All @@ -12,25 +13,41 @@ type oAuthOptions = {
client_id: string,
redirect_uri: string,
response_type: "token" | "code",
receiveToken(): void
receiveToken: any => void
};

type oAuthPollOptions = {
client_id: string,
response_type: "poll_token",
receiveToken: string => void,
onError: Error => void
};

function buildOauthUrl(query) {
return url.format({
protocol: protocol,
hostname: host,
pathname: path,
query: query
});
}

function initOauthToken(options: oAuthOptions) {
const { client_id = false, redirect_uri = false, receiveToken = false, response_type = "token" } = options;
const {
client_id = null,
redirect_uri = null,
receiveToken = null,
response_type = "token"
} = options;

invariant(client_id, "`client_id` is required.");
invariant(redirect_uri, "`redirect_uri` is required.");
invariant(receiveToken, "`receiveToken` is required.");

const oauthUrl = url.format({
protocol: protocol,
hostname: host,
pathname: path,
query: {
redirect_uri: redirect_uri,
client_id: client_id,
response_type: response_type
}
const oauthUrl = buildOauthUrl({
redirect_uri: redirect_uri,
client_id: client_id,
response_type: response_type
});

window.open(oauthUrl, "oauth", "width=680,height=535");
Expand All @@ -40,9 +57,37 @@ function initOauthToken(options: oAuthOptions) {
};
}

function initOauthPollToken(options: oAuthPollOptions) {
const request_id: string = generateRandomString(40);
const { client_id = null, receiveToken = null, onError = null } = options;

invariant(client_id, "`client_id` is required.");
invariant(receiveToken, "`receiveToken` is required.");
invariant(onError, "`onError` is required.");

const oauthUrl = buildOauthUrl({
request_id: request_id,
client_id: client_id,
response_type: "poll_token"
});
const loginOauth = window.open(oauthUrl, "oauth", "width=680,height=535");

ApiMethod("oauth2_token", {
params: { client_id: client_id, request_id: request_id }
})
.then(res => {
receiveToken(res.access_token);
loginOauth.close();
})
.catch(err => {
onError(err);
loginOauth.close();
});
}

function popup() {
const matchToken = (location: any).hash.match(/access_token=([^&]+)/);
const matchCode = (location: any).search.match(/code=([^&]+)/);
const matchToken = location.hash.match(/access_token=([^&]+)/);
const matchCode = location.search.match(/code=([^&]+)/);
const token = matchToken ? matchToken[1] : matchCode[1];

window.opener.__setPcloudToken(token);
Expand All @@ -55,4 +100,9 @@ function getTokenFromCode(code: string, client_id: string, app_secret: string) {
});
}

export default { initOauthToken, popup, getTokenFromCode };
export default {
initOauthToken,
initOauthPollToken,
popup,
getTokenFromCode
};
11 changes: 11 additions & 0 deletions src/utils/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,14 @@ export function methodStringify(method: string, params: Object): string {
export function pCloudUrl(data: DownloadData) {
return "https://" + data.hosts[0] + data.path;
}

export function generateRandomString(length: number) {
const strArr = [];
const base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

for (let i = 0; i < length; i++) {
strArr.push(base[Math.floor(Math.random() * 100)]);
}

return strArr.join("");
}

0 comments on commit 246c3f9

Please sign in to comment.