Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: OAuth 2.0 functionality #290

Open
wants to merge 32 commits into
base: master
Choose a base branch
from

Conversation

berezovskyicom
Copy link
Contributor

@berezovskyicom berezovskyicom commented Jul 10, 2020

This PR adds OAuth2.0 into Abstract SDK.
Link to OAUTH2.0 RFC
Link to OAuth interface for SDK

Adds add getToken() for making a POST request to auth/tokens with authorizationCode.
And setToken() for storing returned accessToken in client.
generateAuthorizeurl() is used for returning an oauth url to Abstract.

Example:

let abstract = new Abstract.Client({
  clientId,
  clientSecret,
  redirectUri,
});

async function oAuth(code) {
  return await abstract.oauth
    .getToken({
      authorizationCode: code
    })
    .then(token => {
      abstract = abstract.oauth.setToken(token);

      return abstract;
    })
    .catch(error => console.log(error));
}

const authorizedAbstract = oAuth("authentication_code");

authorizedAbstract.then(() => {
  // use sdk as usual
});

Things to consider:
client.oauth.setToken() returns new Client({}) with the same options + accessToken.
Is it really possible to change options for Client and all other endpoints without returning a new class?
I've tried a few ways, but the only options get changed are in oauth endpoint. Any thoughts?

src/endpoints/Oauth.js Outdated Show resolved Hide resolved
src/endpoints/Oauth.js Outdated Show resolved Hide resolved
src/endpoints/Oauth.js Outdated Show resolved Hide resolved
src/endpoints/Oauth.js Outdated Show resolved Hide resolved
src/errors.js Outdated Show resolved Hide resolved
src/endpoints/Endpoint.js Outdated Show resolved Hide resolved
@berezovskyicom berezovskyicom changed the title feat(oauth): add getToken() and setToken() methods feat: OAuth 2.0 functionality Jul 13, 2020
@tommoor
Copy link
Contributor

tommoor commented Jul 13, 2020

Looks like a bunch of unrelated work from master is showing up in the PR

Copy link
Contributor

@amccloud amccloud left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for consolidating the PRs 🙏

I think once you get the commits in this PR cleaned up you should be all set for review

body.append("client_id", clientId);
// $FlowFixMe
body.append("client_secret", clientSecret);
// $FlowFixMe
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We typically try to avoid type suppressions unless it is absolutely necessary. If flow is warning here it's likely you have an unaccounted for state here

You can guard appending things to body by either providing a default

body.append("redirect_uri", window.location.href);

or returning early before you pass empty values to the body:

if (!clientId || !clientSecret) {
  throw new Error('OAuthOnAuthorizeToken required');
}

src/types.js Outdated
state: string
};

export type OAuthOnAuthorizeToken = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is the input for getToken

Suggested change
export type OAuthOnAuthorizeToken = {
export type OAuthTokenInput = {

OAuthOnAuthorizeToken seems like what authorizationCode is and that's only part of the input

@tommoor
Copy link
Contributor

tommoor commented Jul 17, 2020

Please move out of draft and re-ping when you're ready for final review.

@berezovskyicom berezovskyicom marked this pull request as ready for review July 20, 2020 22:54
Copy link
Contributor

@amccloud amccloud left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great 👍

Before merging can we start to stub out documentation for this feature? Would be nice to cover what this PR includes

Copy link
Contributor

@tommoor tommoor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost there, I hope to get chance to spin up a sample app to really test before final approval.

abstract-sdk.d.ts Outdated Show resolved Hide resolved
abstract-sdk.d.ts Outdated Show resolved Hide resolved
this.stars = new Stars(this, options);
this.users = new Users(this, options);
this.webhooks = new Webhooks(this, options);
this._analyticsCallback = this.options.analyticsCallback;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should go ahead and just change Endpoint to only accept one argument, this – we can read this.options in the constructor and avoid passing it in essentially twice here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! I left Endpoint options param as optional, because tests were behaving weird.

src/endpoints/Endpoint.js Outdated Show resolved Hide resolved
src/endpoints/OAuth.js Outdated Show resolved Hide resolved
const state = input.state;
const redirectUri = input.redirectUri || this.options.redirectUri;

if (!clientId || !state || !redirectUri) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is state strictly required?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope. Will fix that 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!


return `https://app.abstract.com/signin/auth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(
redirectUri
)}&response_type=code&scope=all&state=${state}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we allow input.scope here to future proof and just set it to "all" as the default?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed.

access_token: string,
client_id: string,
created_at: string,
id: string,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this id?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to back end, it's not used anywhere right now and not much needed for client. Looks like an id in database.

src/Client.js Outdated

setToken(accessToken: string) {
this.options.accessToken = accessToken;
return this.options;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you have a reason for returning options here in mind? Might be confusing, could be better to return this to allow for chaining or nothing at all…

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, 100% agree. Returning nothing lgtm. Will fix that in new commit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed and edited tests.

this.client = client;
this.options = options;
this.options = options ? options : this.client.options;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really sure if that's the best idea, but test are feeling fine.

@berezovskyicom
Copy link
Contributor Author

Me & @Geek-1001 are preparing docs for OAuth, we will let you know when it gets finished!

src/endpoints/OAuth.js Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants