惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
Engineering at Meta
Engineering at Meta
A
About on SuperTechFans
T
The Blog of Author Tim Ferriss
I
InfoQ
博客园_首页
G
Google Developers Blog
爱范儿
爱范儿
Last Week in AI
Last Week in AI
量子位
阮一峰的网络日志
阮一峰的网络日志
雷峰网
雷峰网
酷 壳 – CoolShell
酷 壳 – CoolShell
Vercel News
Vercel News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
GbyAI
GbyAI
月光博客
月光博客
The GitHub Blog
The GitHub Blog
V
Visual Studio Blog
N
Netflix TechBlog - Medium
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东

Netlify Developers

AI model comparison using Netlify's AI Gateway | Netlify Developers Build an AI agent to automatically process and summarize form submissions | Netlify Developers Build an AI agent to automatically generate relevant images for blog posts | Netlify Developers Prerendering SPA content pages to enable AI agent access | Netlify Developers Identify image optimization opportunities with Netlify Observability | Netlify Developers Fix top 404 page not found errors with Netlify Observability | Netlify Developers Introducing AI Gateway: built-in AI model access on Netlify | Netlify Developers Introducing Observability: your project insights on Netlify | Netlify Developers From first publish to first update with AI agents | Netlify Developers How to use Agent Runners on Netlify | Netlify Developers Add forms to your project with AI + Netlify | Netlify Developers Track Real User Metrics | Netlify Developers Lighthouse performance scores on Netlify | Netlify Developers Review your AI project before you ship | Netlify Developers Using environment variables in AI Projects on Netlify | Netlify Developers Build prototypes and MVPs fast with AI + Netlify | Netlify Developers Pause auto-publishing on Netlify | Netlify Developers Run serverless functions, storage, and more natively in Nuxt dev | Netlify Developers Netlify Office Hours: The AX Arcade challenge | Netlify Developers Netlify Office Hours: Prompting with style | Netlify Developers Netlify Office Hours: RAG Apps with OpenAI + Netlify DB | Netlify Developers How to build a RAG application with Neon, Netlify & OpenAI | Netlify Developers Netlify Office Hours: Netlify DB (powered by Neon) | Netlify Developers Netlify Office Hours: Netlify MCP Server | Netlify Developers Netlify Office Hours: Netlify Vite Plugin | Netlify Developers Building MCPs with Netlify | Netlify Developers Deploying sites from your AI tool | Netlify Developers Adding your domain using Netlify API | Netlify Developers Build a context driven chat bot with Netlify Blob and OpenAI | Netlify Developers Simplify deployments with Netlify’s branch-matching environment variables | Netlify Developers
Generate personal access tokens with Netlify OAuth | Netl...
2025-03-18 · via Netlify Developers

Every action available in the Netlify UI is powered by an API endpoint. This means you can integrate these same capabilities directly into your own tools and automation workflows.

We’re going to walk through a process that generates the access token you’ll need to act on behalf of your users to do things like:

  • Engage in CI/CD flows for your users
  • Manage account and user information
  • Take actions on behalf of your users

With these actions comes the risk of bad actors circumventing your access and using it nefariously. While showing you this workflow, we’ll also work through building safeguards to help protect you and your users.

#What are we building?

This is going to be a simple static site where:

  1. We create an OAuth app that determines the redirect URL.
  2. We craft and visit a URL with our client id, our redirect URL for the user to approve, and our generated state.
  3. After approving, Netlify redirects to the redirect URL with the token in the URL
  4. This token will be used when making calls to the API on behalf of the user.
  5. We then use this token to call a Netlify API and generate a Personal Access Token.

#Create an OAuth application

Before we dive into the code, we need to create a new OAuth application. From the Netlify Dashboard navigate to your “User Settings” and from there to Applications.

Select “New OAuth app” and fill in any details for your project. For this guide we’ve filled it in as follows:

The form presented when creating a new OAuth application in the Netlify settings

Save your Client ID and Secet key somewhere safe. You’ll be using the Client ID in your app.js file in the next section.

With that setup, we can move into the code.

#Create and setup the application

Since we’re not going to use any frameworks, getting set up is as easy as creating a folder with two files: app.js and index.html in your project directory.

First, let’s set up our HTML so we have elements we can utilize in our js file.

<!doctype html>

<html>

<head>

<title>Netlify OAuth & Personal Access Token Generation</title>

</head>

<body>

<h1>Netlify OAuth & PAT Generation</h1>

<button id="oauth-button">Start OAuth Flow</button>

<script src="/app.js"></script>

</body>

</html>

Next, we’ll fill in our app file:

// Input your CLIENT_ID here -- this ID fine to be public and is needed to craft our OAuth URL

const CLIENT_ID = "";

const REDIRECT_URI = "http://localhost:8888/";

// Simple and secure way to generate state. This state is used to help us prevent CSRF attacks while moving through the OAuth flow

function generateState() {

return crypto.randomUUID();

}

function handleNetlifyOAuth() {

const clientId = CLIENT_ID;

const redirectUri = REDIRECT_URI;

const state = generateState();

// Setting our state enables us to use the value to check the validity of the requester

localStorage.setItem('oauth_state', state);

const authLink = `https://app.netlify.com/authorize?client_id=${clientId}&response_type=token&redirect_uri=${redirectUri}&state=${state}`;

window.location.href = authLink;

}

document.addEventListener('DOMContentLoaded', () => {

const oAuthButton = document.querySelector("#oauth-button");

if (oAuthButton) {

oAuthButton.addEventListener("click", handleNetlifyOAuth);

} else {

console.error('OAuth button not found');

}

});

const hash = document.location.hash;

/*

* This function is called when a user returns from Netlify and has accepted the

* request to authorize your app.

*

* It extracts the token from the response and use it to do a simple API request

* fetching the latest sites from the user from Netlify.

*/

function handleAccessToken() {

// The access token is returned in the hash part of the document.location

// #access_token=1234&response_type=token&state=...

const response = new URLSearchParams(hash.replace(/^#/, ''));

const state = response.get('state');

const accessToken = response.get('access_token')

const savedState = localStorage.getItem('oauth_state');

// Clean up immediately

localStorage.removeItem('oauth_state');

if (!savedState || savedState !== state) {

console.log('Security Error: Invalid state parameter. Possible CSRF attack.');

return;

}

// Remove the token so it's not visible in the URL after we're done

document.location.hash = '';

// Send the access token to the create-token endpoint to generate a PAT

fetch('/create-token', {

method: "POST",

headers: {

'Authorization': `Bearer ${accessToken}`,

'Content-Type': 'application/json'

}

})

.then(response => response.json())

.then(json => {

console.log(json);

})

.catch(error => {

console.log(error)

});

}

/*

* If we have any hash, it's because the user is coming back from Netlify and we

* can start doing API requests on their behalf.

*/

if (document.location.hash) {

handleAccessToken();

}

While the comments above do a decent job of breaking down the pieces of our js file — let’s take a moment to understand what’s happening:

  1. Set the variables for the needed CLIENT_ID and our REDIRECT_URI (we’re using localhost:8888 since we’re using netlify dev as our development server)
  2. Generate a random UUID to help track the state of the request returned back after completing the OAuth flow
  3. Build our OAuth URL from a few of the variables we’ve created so far to attach to our button back in the HTML code
  4. Once the OAuth flow is finished and we return a successful hash, we extract the values we need from the hash. We make sure the state matches, clear the hash from the URL, and begin the fetch to our /create-token endpoint
  5. Finally, we make sure we only handle the token if there is a hash located in the URL

All that’s left is to wire up our serverless function and generate our personal access token.

#Generating a personal access token

Let’s start by installing our single dependency in our project to help setup our function

npm install @netlify/functions

After successful OAuth authentication, the returned access token can be used as a Bearer token for Netlify API calls. However, for more granular control over authentication, Personal Access Tokens (PATs) provide additional benefits. PATs offer configurable lifespans and enhanced security features that may be better suited for production environments.

We will build an example of protecting our function using the OAuth access token, while also passing through that token to an API call generating our PAT.

Let’s create a file for our function using Netlify’s functions folder named create-token.ts and fill in our function:

import type { Context, Config } from "@netlify/functions"

export default async (req: Request, context: Context) => {

const accessToken = req.headers.get('Authorization')?.split(' ')[1]

if (!accessToken) {

return new Response('Unauthorized', { status: 401 })

}

try {

// Our fetch to our endpoint that creates the PAT includes a body describing the structure we explained earlier

const response = await fetch('https://api.netlify.com/api/v1/oauth/applications/create_token', {

method: 'POST',

headers: {

'Authorization': `Bearer ${accessToken}`,

'Content-Type': 'application/json'

},

body: JSON.stringify({

administrator_id: null,

expires_in: 604800,

grant_saml: false,

name: "token-from-state-example"

})

})

const data = await response.json()

return new Response(JSON.stringify({message: "Token created successfully!"}), {

headers: { 'Content-Type': 'application/json' }

})

} catch (error) {

return new Response(JSON.stringify({ error: 'Failed to create token' }), {

status: 500,

headers: { 'Content-Type': 'application/json' }

})

}

}

// This path config makes calling the endpoint easier, without having to match the route of the document

export const config: Config = {

path: "/create-token"

}

Above you’ll see we take and check for the access token we’ve sent through our original fetch. Applying that same token to the POST request that creates our new PAT and return a success message. This token is now usable, within it’s lifespan, to authorize new API requests made to Netlify.

#Final Thoughts

We’ve got everything we need to continue building out new API requests to Netlify. If you’d like to see the code we’ve built in repo, feel free to visit our examples repo and good luck with your projects!