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(providers): Adding HubSpot Provider #4633

Merged
merged 16 commits into from Sep 11, 2022
Merged
2 changes: 1 addition & 1 deletion SECURITY.md
Expand Up @@ -15,7 +15,7 @@ If you contact us regarding a serious issue:

The best way to report an issue is by contacting us via email at info@balazsorban.com or me@iaincollins.com and yo@ndo.dev, or raise a public issue requesting someone get in touch with you via whatever means you prefer for more details. (Please do not disclose sensitive details publicly at this stage.)

> For less serious issues (e.g. RFC compliance for unsupported flows or potential issues that may cause a problem in the future) it is appropriate to submit these these publically as bug reports or feature requests or to raise a question to open a discussion around them.
> For less serious issues (e.g. RFC compliance for unsupported flows or potential issues that may cause a problem in the future) it is appropriate to submit these publicly as bug reports or feature requests or to raise a question to open a discussion around them.
Miciurash marked this conversation as resolved.
Show resolved Hide resolved

## Supported Versions

Expand Down
43 changes: 43 additions & 0 deletions docs/docs/providers/hubspot.md
@@ -0,0 +1,43 @@
---
id: hubspot
title: HubSpot
---

:::note
HubSpot returns a limited amount of information on the token holder (see [docs](https://legacydocs.hubspot.com/docs/methods/oauth2/get-access-token-information)). One other issue is that the name and profile photo cannot be fetched through API as discussed [here](https://community.hubspot.com/t5/APIs-Integrations/Profile-photo-is-not-retrieved-with-User-API/m-p/325521).
:::

## Documentation

https://developers.hubspot.com/docs/api/oauth-quickstart-guide

## Configuration

You need to have an APP in your Developer Account as described at https://developers.hubspot.com/docs/api/developer-tools-overview

## Options

The **HubSpot Provider** comes with a set of default options:

- [HubSpot Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/hubspot.js)
Miciurash marked this conversation as resolved.
Show resolved Hide resolved

You can override any of the options to suit your own use case.

## Example

```js
import HubspotProvider from "next-auth/providers/hubspot";
...
providers: [
HubspotProvider({
clientId: process.env.HUBSPOT_CLIENT_ID,
clientSecret: process.env.HUBSPOT_CLIENT_SECRET
})
]
...
```

:::warning
Only allows one callback URL per Client ID / Client Secret and the redirect URL must be the same as the one on the HubSpot APP Settings page.
:::

104 changes: 104 additions & 0 deletions packages/next-auth/src/providers/hubspot.ts
@@ -0,0 +1,104 @@
import type { OAuthConfig, OAuthUserConfig } from "."

interface HubSpotProfile extends Record<string, any> {

// TODO: figure out additional fields, for now using
// https://legacydocs.hubspot.com/docs/methods/oauth2/get-access-token-information

user: string,
user_id: string,

hub_domain: string,
hub_id: string,
}


const HubSpotConfig = {
clientId: process.env.HUBSPOT_CLIENT_ID ?? "DEFAULT_CLIENT_ID",
Miciurash marked this conversation as resolved.
Show resolved Hide resolved
clientSecret: process.env.HUBSPOT_CLIENT_SECRET ?? "DEFAULT_CLIENT_SECRET",
redirectUri: process.env.HUBSPOT_REDIRECT_URI ?? "DEFAULT_REDIRECT_URI",
authorizationUrl: "https://app.hubspot.com/oauth/authorize",
tokenUrl: "https://api.hubapi.com/oauth/v1/token",
profileUrl: "https://api.hubapi.com/oauth/v1/access-tokens/"
Miciurash marked this conversation as resolved.
Show resolved Hide resolved
}

export default function HubSpot<P extends HubSpotProfile>(
options: OAuthUserConfig<P> & { "redirectURL": string }
Miciurash marked this conversation as resolved.
Show resolved Hide resolved
): OAuthConfig<P> {

return {
id: "hubspot",
name: "HubSpot",
type: "oauth",

...HubSpotConfig,

authorization: {
url: HubSpotConfig.authorizationUrl,
params: {
scope: "oauth contacts",
Miciurash marked this conversation as resolved.
Show resolved Hide resolved
redirect_uri: HubSpotConfig.redirectUri,
client_id: HubSpotConfig.clientId,
},

},
token: {
url: HubSpotConfig.tokenUrl,
async request(context) {
Miciurash marked this conversation as resolved.
Show resolved Hide resolved

const url = HubSpotConfig.tokenUrl + "?" +
new URLSearchParams({
client_id: HubSpotConfig.clientId,
client_secret: HubSpotConfig.clientSecret,
grant_type: "authorization_code",
redirect_uri: HubSpotConfig.redirectUri,
code: context.params.code ?? "DEFAULT_CODE",
});

const response = await fetch(url, {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
method: "POST",
});

const tokens = await response.json()

return { tokens };
},
},
userinfo: {
url: HubSpotConfig.profileUrl,
async request(context) {

const url = `${HubSpotConfig.profileUrl}/${context.tokens.access_token}`;

const response = await fetch(url, {
headers: {
"Content-Type": "application/json",
},
method: "GET",
});

const userInfo = await response.json();

return { userInfo }
}
},
profile(profile) {

const { userInfo } = profile

return {
id: userInfo.user_id,
name: userInfo.user,
email: userInfo.user,

// TODO: get image from profile once it's available
// Details available https://community.hubspot.com/t5/APIs-Integrations/Profile-photo-is-not-retrieved-with-User-API/m-p/325521
image: "https://avatars.hubspot.net/default-100",
Miciurash marked this conversation as resolved.
Show resolved Hide resolved
}
},
options,
}
}