|
| 1 | +import { Callout } from "nextra/components" |
| 2 | +import { Code } from "@/components/Code" |
| 3 | + |
| 4 | +<img align="right" src="/img/providers/netsuite.svg" height="64" width="64" /> |
| 5 | + |
| 6 | +# NetSuite |
| 7 | + |
| 8 | +## Resources |
| 9 | + |
| 10 | +- [NetSuite - Creating an Integration Record (OAuth 2.0)](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_157771733782.html#Related-Topics) |
| 11 | +- [NetSuite - Authorizing OAuth Requests](https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps) |
| 12 | +- [NetSuite - Configure OAuth Roles](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_157771510070.html#Set-Up-OAuth-2.0-Roles) |
| 13 | +- [Learn more about NetSuite OAuth 2.0](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/chapter_157769826287.html#OAuth-2.0) |
| 14 | + |
| 15 | +## Setup |
| 16 | + |
| 17 | +### Callback URL |
| 18 | + |
| 19 | +<Callout> |
| 20 | + NetSuite does not support http. When testing locally, you can use a service |
| 21 | + like [ngrok](https://ngrok.com) to get a local https URL. |
| 22 | +</Callout> |
| 23 | + |
| 24 | +<Code> |
| 25 | + <Code.Next> |
| 26 | + |
| 27 | +```bash |
| 28 | +https://example.com/api/auth/callback/netsuite |
| 29 | +``` |
| 30 | + |
| 31 | + </Code.Next> |
| 32 | + <Code.Svelte> |
| 33 | + |
| 34 | +```bash |
| 35 | +https://example.com/auth/callback/netsuite |
| 36 | +``` |
| 37 | + |
| 38 | + </Code.Svelte> |
| 39 | +</Code> |
| 40 | + |
| 41 | +### Userinfo RESTlet |
| 42 | + |
| 43 | +Our `userinfo` URL needs to be a suitelet or RESTLet URL that gives us the |
| 44 | +information about the user. The best bet is to use the `N/runtime` module to |
| 45 | +get the basics first. - Here is an example of a RESTlet below. Be sure to |
| 46 | +deploy and enable access to "All Roles". |
| 47 | + |
| 48 | +### Example RESTLet Callback Handler |
| 49 | + |
| 50 | +Be sure to deploy and use the **external** RESTLet url of any usage of the URIs. |
| 51 | + |
| 52 | +```js |
| 53 | +/** |
| 54 | + * @NApiVersion 2.1 |
| 55 | + * @NScriptType Restlet |
| 56 | + */ |
| 57 | +define(["N/runtime"], |
| 58 | + @param{runtime} runtimee |
| 59 | + (runtime) => { |
| 60 | + /** |
| 61 | + * Defines the function that is executed when a GET request is sent to a RESTlet. |
| 62 | + * @param {Object} requestParams - Parameters from HTTP request URL; parameters passed as an Object (for all supported |
| 63 | + * content types) |
| 64 | + * @returns {string | Object} HTTP response body; returns a string when request Content-Type is 'text/plain'; returns an |
| 65 | + * Object when request Content-Type is 'application/json' or 'application/xml' |
| 66 | + * @since 2015.2 |
| 67 | + *\/ |
| 68 | + const get = (requestParams) => { |
| 69 | + let userObject = runtime.getCurrentUser(); |
| 70 | +
|
| 71 | + try { |
| 72 | + log.debug({ title: "Payload received:", details: requestParams }); |
| 73 | +
|
| 74 | + const { id, name, role, location, email, contact } = userObject; |
| 75 | +
|
| 76 | + log.audit({ title: "Current User Ran", details: name }); |
| 77 | +
|
| 78 | + let user = { |
| 79 | + id, |
| 80 | + name, |
| 81 | + role, |
| 82 | + location, |
| 83 | + email, |
| 84 | + contact, |
| 85 | + }; |
| 86 | +
|
| 87 | + log.debug({ title: "Returning user", details: user }); |
| 88 | +
|
| 89 | + return JSON.stringify(user); |
| 90 | + } catch (e) { |
| 91 | + log.error({ title: "Error grabbing current user:", details: e }); |
| 92 | + } |
| 93 | + }; |
| 94 | +
|
| 95 | + return { |
| 96 | + get, |
| 97 | + }; |
| 98 | +); |
| 99 | +``` |
| 100 | +
|
| 101 | +Above is an example of returning the basic runtime information. Be sure to create a new script record and deployment record. When you save the deployment record, you will get the URLs for your RESTlet, which we will use as the `userinfo` URL. |
| 102 | +
|
| 103 | +### Environment Variables |
| 104 | +
|
| 105 | +``` |
| 106 | +AUTH_NETSUITE_ID |
| 107 | +AUTH_NETSUITE_SECRET |
| 108 | +``` |
| 109 | +
|
| 110 | +### Configuration |
| 111 | +
|
| 112 | +Before setting up the provider, you will need to ensure the following is setup. |
| 113 | +
|
| 114 | +- [Create an Integration Record](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_157771733782.html#procedure_157838925981) |
| 115 | + - Uncheck the TBA Auth Flow checkbox. |
| 116 | + - Check OAuth 2.0 Auth Flow checkbox. |
| 117 | + - Copy and paste the `Callback URL` below into the `Redirect URI` field. |
| 118 | + - Then select the scope(s) you want to use. |
| 119 | + - **REST Web Services** (`rest_webservices`) - Access to REST Web Services. |
| 120 | + - **RESTlets**(`restlets`) - Access to RESTLets. |
| 121 | + - **SuiteAnalytics Connect** (`suiteanalytics_connect`) - Access to SuiteAnalytics Connect. |
| 122 | + - Add any policies you want to use. |
| 123 | + - Application Logo (_Optional_) (Shown to users when they are asked to grant access to your application). - Consent Screen |
| 124 | + - Application Terms of Use (_Optional_) - A PDF file that contains the terms of use for your application. - Consent Screen |
| 125 | + - Application Privacy Policy (_Optional_) - A PDF file that contains the privacy policy for your application. - Consent Screen |
| 126 | + - OAuth 2.0 Consent Policy Preference - This setting determines whether the user is asked to grant access to your application **every time** they sign in or only the **first time** they sign in or **never**. |
| 127 | + - **Save** the Integration record. |
| 128 | + - The Integration record will be used to generate the `clientId` and `clientSecret` for the provider. **Save the generated values for later** |
| 129 | +
|
| 130 | +<Code> |
| 131 | + <Code.Next> |
| 132 | +
|
| 133 | +```ts filename="/auth.ts" |
| 134 | +import NextAuth from "next-auth" |
| 135 | +import NetSuite from "next-auth/providers/netsuite" |
| 136 | +
|
| 137 | +export const { handlers, auth, signIn, signOut } = NextAuth({ |
| 138 | + providers: [ |
| 139 | + NetSuite({ |
| 140 | + clientId: AUTH_NETSUITE_ID, |
| 141 | + clientSecret: AUTH_NETSUITE_SECRET, |
| 142 | + issuer: AUTH_NETSUITE_ACCOUNT_ID, // EX: TSTDRV1234567 or 81555 for prod, and 1234567-SB1 for Sandbox accounts not "_" use "-". |
| 143 | + // Returns the current user using the N/runtime module. This url can be a suitelet or RESTlet (Recommended) |
| 144 | + // Using getCurrentUser(); So we match this schema returned from this RESTlet in the profile callback. (Required) |
| 145 | + userinfo: |
| 146 | + "https://1234567.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=123&deploy=1", |
| 147 | + // Optional |
| 148 | + prompt: "login", // Required if you want to force the user to login every time. |
| 149 | + scope: "restlets", // Optional defaults to "restlets rest_webservices". Enter the scope(s) you want to use followed by spaces. |
| 150 | + }), |
| 151 | + ], |
| 152 | +}) |
| 153 | +``` |
| 154 | +
|
| 155 | + </Code.Next> |
| 156 | + <Code.Svelte> |
| 157 | +
|
| 158 | +```ts filename="/src/auth.ts" |
| 159 | +import { SvelteKitAuth } from "@auth/sveltekit" |
| 160 | +import NetSuite from "@auth/sveltekit/providers/netsuite" |
| 161 | +
|
| 162 | +export const { handle, signIn, signOut } = SvelteKitAuth({ |
| 163 | + providers: [ |
| 164 | + NetSuite({ |
| 165 | + clientId: AUTH_NETSUITE_ID, |
| 166 | + clientSecret: AUTH_NETSUITE_SECRET, |
| 167 | + issuer: AUTH_NETSUITE_ACCOUNT_ID, // EX: TSTDRV1234567 or 81555 for prod, and 1234567-SB1 for Sandbox accounts not "_" use "-". |
| 168 | + // Returns the current user using the N/runtime module. This url can be a suitelet or RESTlet (Recommended) |
| 169 | + // Using getCurrentUser(); So we match this schema returned from this RESTlet in the profile callback. (Required) |
| 170 | + userinfo: |
| 171 | + "https://1234567.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=123&deploy=1", |
| 172 | + // Optional |
| 173 | + prompt: "login", // Required if you want to force the user to login every time. |
| 174 | + scope: "restlets", // Optional defaults to "restlets rest_webservices". Enter the scope(s) you want to use followed by spaces. |
| 175 | + }), |
| 176 | + ], |
| 177 | +}) |
| 178 | +``` |
| 179 | +
|
| 180 | + </Code.Svelte> |
| 181 | + <Code.Express> |
| 182 | +
|
| 183 | +```ts filename="/src/app.ts" |
| 184 | +import { ExpressAuth } from "@auth/express" |
| 185 | +import NetSuite from "@auth/express/providers/netsuite" |
| 186 | +
|
| 187 | +app.use( |
| 188 | + "/auth/*", |
| 189 | + ExpressAuth({ |
| 190 | + providers: [ |
| 191 | + NetSuite({ |
| 192 | + clientId: AUTH_NETSUITE_ID, |
| 193 | + clientSecret: AUTH_NETSUITE_SECRET, |
| 194 | + issuer: AUTH_NETSUITE_ACCOUNT_ID, // EX: TSTDRV1234567 or 81555 for prod, and 1234567-SB1 for Sandbox accounts not "_" use "-". |
| 195 | + // Returns the current user using the N/runtime module. This url can be a suitelet or RESTlet (Recommended) |
| 196 | + // Using getCurrentUser(); So we match this schema returned from this RESTlet in the profile callback. (Required) |
| 197 | + userinfo: |
| 198 | + "https://1234567.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=123&deploy=1", |
| 199 | + // Optional |
| 200 | + prompt: "login", // Required if you want to force the user to login every time. |
| 201 | + scope: "restlets", // Optional defaults to "restlets rest_webservices". Enter the scope(s) you want to use followed by spaces. |
| 202 | + }), |
| 203 | + ], |
| 204 | + }) |
| 205 | +) |
| 206 | +``` |
| 207 | +
|
| 208 | + </Code.Express> |
| 209 | +</Code> |
0 commit comments