Authentication 

The openai-screenwriter-tutorial-v2 API uses GraphQL over HTTPS to communicate with clients. Purpose-built GraphQL clients as well as HTTP clients like fetch, cURL, or the HTTP library for your programming language of choice can be used to communicate with your Gadget app's API.

Gadget generates a JavaScript client for the openai-screenwriter-tutorial-v2 API which handles authentication automatically. We recommend using these clients where possible.

Authentication modes 

The Gadget API supports three different authentication modes:

ModeDescriptionUse cases
Browser Session authenticationGadget stores a session token (similar to a cookie) in the user's browser, and sends it in the Authorization headerClient-side applications, browser single sign-on, user login/logout flows
Anonymous authenticationNo authentication header sent at allPublicly accessible data, ecommerce storefronts
API Key authenticationCopy a gsk-xxxxxx API Key from the API Keys page in the editor, and pass it in the Authorization headerServer-to-server communication, bots, scripts
Shopify Session TokenAuth managed by Shopify's session tokens and @gadgetinc/react-shopify-app-bridgeApps embedded in the Shopify admin

The API client will use Browser Session authentication by default if it detects that it's running in a browser environment, and use Anonymous authentication by default if not running in a browser.

Browser session authentication 

Gadget can use session tokens to authenticate individual users to the backend. Session tokens work similarly to cookies. Clients will receive a private session token representing that one client's browser, and the token will be represented in the backend by one record of the application's Session model. The client can then run Actions on this session record to change their authorization state.

If you're building a client-side application where authenticated users should have access to different data than unauthenticated users, then Browser Session Authentication is a great option. Unauthenticated users will have the Unauthenticated role which can allow them to access some data (or none at all), and then once a user logs in, they can be given a role with different permissions.

Browser Session authentication with Gadget works quite similarly to cookie-based authentication in other systems, but Gadget doesn't actually use cookies under the hood to make cross-domain authentication work better across different browsers. Instead, Gadget uses the Authorization header to implement a similar scheme, and the generated JavaScript client uses localStorage to store the private session token.

Read more about implementing roles and permissions for your app in the Access Control guide.

Enabling browser authentication 

If you're using the Gadget JavaScript client for openai-screenwriter-tutorial-v2 in a browser context, and you want to allow the user to log in and stay logged in, you can request that the Gadget client track a user's session token with the browserSession: true authentication mode.

JavaScript
1import { Client } from "@gadget-client/openai-screenwriter-tutorial-v2";
2const client = new Client({
3 authenticationMode: {
4 browserSession: true,
5 },
6});
1import { Client } from "@gadget-client/openai-screenwriter-tutorial-v2";
2const client = new Client({
3 authenticationMode: {
4 browserSession: true,
5 },
6});

Storage modes for session persistence 

The JS client has three modes for storing the session token which uniquely identifies the user to allow full configuration of how long a user's session might last. To configure which storage mode is used for session token persistence, pass the storageType option like so:

JavaScript
1import {
2 Client,
3 BrowserSessionStorageType,
4} from "@gadget-client/openai-screenwriter-tutorial-v2";
5const api = new Client({
6 authenticationMode: {
7 browserSession: {
8 storageType: BrowserSessionStorageType.Session,
9 },
10 },
11});
1import {
2 Client,
3 BrowserSessionStorageType,
4} from "@gadget-client/openai-screenwriter-tutorial-v2";
5const api = new Client({
6 authenticationMode: {
7 browserSession: {
8 storageType: BrowserSessionStorageType.Session,
9 },
10 },
11});

Long-lived sessions with BrowserSessionStorageType.Durable (Default) 

In this mode, the client will persist the user's session token using window.localStorage. This means the user's session will last generally a long time -- until the user clears local storage or the browser decides it has expired. This option is a good default for applications where users log in and can stay logged in for a long time.

Create a client with durable session token storage
JavaScript
1import {
2 Client,
3 BrowserSessionStorageType,
4} from "@gadget-client/openai-screenwriter-tutorial-v2";
5const api = new Client({
6 authenticationMode: {
7 browserSession: {
8 storageType: BrowserSessionStorageType.Durable,
9 },
10 },
11});
1import {
2 Client,
3 BrowserSessionStorageType,
4} from "@gadget-client/openai-screenwriter-tutorial-v2";
5const api = new Client({
6 authenticationMode: {
7 browserSession: {
8 storageType: BrowserSessionStorageType.Durable,
9 },
10 },
11});

Short-term sessions with BrowserSessionStorageType.Session 

In this mode, the client will persist the user's session token using window.sessionStorage. This means the user's session will last until they close the tab, which is generally a short time. Users can navigate between pages of the application, or open new tabs and preserve it, but generally sessions stored with BrowserSessionStorageType.Session will be short lived.

This option is a good default for applications where users log in to something very sensitive, or for applications where the user's identity is ephemeral like a browser game or sales chat app.

Create a client with session-length token storage
JavaScript
1import {
2 Client,
3 BrowserSessionStorageType,
4} from "@gadget-client/openai-screenwriter-tutorial-v2";
5const api = new Client({
6 authenticationMode: {
7 browserSession: {
8 storageType: BrowserSessionStorageType.Session,
9 },
10 },
11});
1import {
2 Client,
3 BrowserSessionStorageType,
4} from "@gadget-client/openai-screenwriter-tutorial-v2";
5const api = new Client({
6 authenticationMode: {
7 browserSession: {
8 storageType: BrowserSessionStorageType.Session,
9 },
10 },
11});

Single page sessions with BrowserSessionStorageType.InMemory 

In this mode, the client will not persist the user's session, so it will only last while that one page is active in the user's browser. This means the user's session will last until they navigate away from the page, close the tab, refresh, or do anything to reset the JS context of the page, which is generally a short time.

Create a client with session-length token storage
JavaScript
1import {
2 Client,
3 BrowserSessionStorageType,
4} from "@gadget-client/openai-screenwriter-tutorial-v2";
5const api = new Client({
6 authenticationMode: {
7 browserSession: {
8 storageType: BrowserSessionStorageType.Session,
9 },
10 },
11});
1import {
2 Client,
3 BrowserSessionStorageType,
4} from "@gadget-client/openai-screenwriter-tutorial-v2";
5const api = new Client({
6 authenticationMode: {
7 browserSession: {
8 storageType: BrowserSessionStorageType.Session,
9 },
10 },
11});

Anonymous authentication 

It can be convenient to allow anyone without an API Key to access some data in your application. For example, anyone on the internet should be able to visit a blog and read the posts, or visit an ecommerce storefront and view the products, so no authentication is needed for this kind of data.

To use Anonymous authentication, make requests without sending an API key or a browser session token. Requests to the openai-screenwriter-tutorial-v2 app without any authentication information will be assigned the Unauthenticated role. The Gadget application developer will need to grant the Unauthenticated role permission to access this publicly-available data. If the Unauthenticated Role for the application hasn't been granted any permissions, requests made without an API Key won't be able to read or write any data.

To create a client that uses no authentication, pass anonymous: true to the authenticationMode option when creating the client:

JavaScript
1import { Client } from "@gadget-client/openai-screenwriter-tutorial-v2";
2const client = new Client({
3 authenticationMode: {
4 anonymous: true,
5 },
6});
1import { Client } from "@gadget-client/openai-screenwriter-tutorial-v2";
2const client = new Client({
3 authenticationMode: {
4 anonymous: true,
5 },
6});

API key authentication 

The Gadget API uses API Keys to authenticate requests. API keys are secret strings accessible through the Gadget Editor. API Keys grant the holder permission to read and write different pieces of data depending on which roles the key has been assigned.

API Keys always start with the three letters gsk (standing for Gadget Secret Key), so they look something like gsk-a1z1z1z1z1z1z1z1z11z. Security best practices mandate that you don't commit sensitive data like API keys to your code base, and instead use something like environment variables to pass them to code in production. GitGuardian has a great reference on how to accomplish this.

Don't send API keys to the browser as they can be read from the source code and used for malicious purposes.

API Key authentication is useful for server-to-server communication where the client code is trusted.

If you're building a server-side application that will write data to the openai-screenwriter-tutorial-v2 datastore, API keys are the easiest way to authenticate and limit permissions.

Sending an API key 

If you're using the Gadget JavaScript client for openai-screenwriter-tutorial-v2, you can pass your API Key as an option to the client when constructing it.

JavaScript
const client = new Gadget({
authenticationMode: { apiKey: "gsk-a1z1z1z1z1z1z1z1z11z" },
});
const client = new Gadget({
authenticationMode: { apiKey: "gsk-a1z1z1z1z1z1z1z1z11z" },
});

The client object will automatically pass the API Key to the API for each request it makes.

If you're making requests using some other HTTP client, you must pass the API Key as the token using HTTP Bearer Auth. HTTP requests to the GraphQL endpoint at https://openai-screenwriter-tutorial-v2--development.gadget.app/api/graphql should use Bearer Token authentication in the headers to do this.

This means passing the HTTP Authorization header with the value Bearer gsk-a1z1z1z1z1z1z1z1z11z, replacing that example API Key with a valid API Key from the Gadget Editor.

For example, you can make an authenticated request with curl by passing the Authorization header.

terminal
curl -H "Authorization: Bearer gsk-a1z1z1z1z1z1z1z1z11z" -X POST https://openai-screenwriter-tutorial-v2--development.gadget.app/api/graphql ...

Authentication failures 

If an invalid API Key is passed to Gadget, the API will return an error in the GraphQL error format as a JSON response like so:

json
1{
2 "errors": [
3 {
4 "message": "Invalid API Key."
5 }
6 ],
7 "data": null
8}

This error is only returned if an API Key is used to authenticate. If no Authorization header is sent with the request, which means no API Key has been passed, Gadget treats the request as an anonymous one, and permits or denies access to data using the Unauthenticated role.

Enabling authentication with the React client 

The urql client (built on top of the Gadget React bindings) that the openai-screenwriter-tutorial-v2 client provides is pre-configured to connect to the right Gadget platform GraphQL endpoint and uses the same authentication mechanism that the outer Gadget client uses. If you configure the Gadget client to use a browser session, the urql client will use the same browser session. If you configure you Gadget client to use API key authentication, the urql client will use that same API key.

React is a client side framework and your code is likely to be visible to all the users of your application. For this reason, Gadget recommends using Session Cookie based authentication for accessing the Gadget API. You shouldn't use an API key that has write permissions for authenticating as that API key will be available to any client and ripe for abuse. You can instead use session-based authentication where users must log in to get privileges, or you can leave the client in the unauthenticated mode and grant permissions to read some backend data to the Unauthenticated role.

Was this page helpful?