auth-app.js
auth-app.js copied to clipboard
[DOCS]: Implementation of GitHub App user authentication token with expiring disabled
Describe the need
Attempting to create a GitHub App user authentication token with expiring disabled. (Sidenote, is it the same as a user-to-server token? The language on docs is not clear.)
-
We have a Github App
-
We have Opted-Out of the "User-to-server token expiration" in App Settings > Optional features.
-
Attempting to generate a non-expiring token using
@octokit/auth-app -
We tried two approaches to generate a token, using JWT and Installation token as Authentication Objects for the
createOAuthUserAuthfunction.
import * as dotenv from 'dotenv';
import { Octokit } from '@octokit/core';
import { createAppAuth, createOAuthUserAuth } from '@octokit/auth-app';
/**
* Using Github App (JWT)
*/
export const getTokenUsingJwt = async (service: any, SecretKey: any): Promise<string> => {
try {
dotenv.config();
const appId = process.env.APP_ID as string;
const privateKey = SecretKey?.SecretString as string;
const clientId = process.env.CLIENT_ID as string;
const clientSecret = process.env.CLIENT_SECRET as string;
const installationId = service.metadata.installation as number;
// Create a new Octokit instance using App Authentication
const appAuth = createAppAuth({
appId: Number(appId),
privateKey,
});
// Authenticate as the GitHub App
const appAuthentication = await appAuth({
type: 'app',
});
const appAuthenticationToken = appAuthentication.token;
// console.log('App authentication token', appAuthenticationToken);
// Create an OAuth user authentication for the specified installation
const authenticated = createOAuthUserAuth({
clientType: "github-app",
clientId,
clientSecret,
token: appAuthenticationToken,
});
// Get the user-to-server authentication token
const { token, type, tokenType } = await authenticated();
return token; // type: token, tokenType: oauth
} catch(error) {
throw error;
}
}
/**
* Using Installation
*/
export const getTokenUsingInstallation = async (service: any, SecretKey: any): Promise<string> => {
try {
dotenv.config();
const appId = process.env.APP_ID as string;
const privateKey = SecretKey?.SecretString as string;
const clientId = process.env.CLIENT_ID as string;
const clientSecret = process.env.CLIENT_SECRET as string;
const installationId = service.metadata.installation as number;
// Step 1: Authenticate as your GitHub App using a JWT
const appAuth = createAppAuth({
appId: Number(appId),
privateKey: privateKey,
});
// Create an installation access token to act on behalf of the GitHub App installation
const installationAuthentication = await appAuth({
type: 'installation',
installationId
});
const installationAccessToken = installationAuthentication.token;
// console.log('Installation token', installationAccessToken);
// Step 2: Create OAuth user-to-server access token using the installation access token
const authenticated = createOAuthUserAuth({
clientType: "github-app",
clientId,
clientSecret,
token: installationAccessToken,
});
// Get the user-to-server access token
const { token, type, tokenType } = await authenticated({ type: 'get' });
return token; // type: token, tokenType: oauth
} catch(error) {
throw error;
}
}
JWT approach produces a token such as:
eyJhkGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE2OTE2NjkzMDMsImV4cCI6MTY5MTY2OTkwMywiaXNzIjoyNzI1NjZ9.gaUOyjWkbm7NrfhNayPYwK1EzMyeUlEuWTTd7OEpBS91pY6wjCJx_giNOJBzNf0gzMwCyycxtjUCiMU1g6J0xgaYH_2iZxNeoakKYztHxccG8lzBUDCaTwgMBeeFxErlsW02WX8-b8nh0kEr07prYr7mwZFs2i5vEjgJznvk7NU7rzknXBzPeac5DZNq-NO6ikb_BTlMq1z7sW9SXU7xrEM8uHyVvk2KIYvkpwqRvoFBAeWuIIP1UotORxnLqAcLa5AIgOB3vg3Fonhv7d65NfbT9S1A6bfNjXJ25fZvzLoSRgCjTmR1St4MqgsK6O71ThjEk_GELnAm2LEwBt_VuQ
The installation token approach produces a token such as this. However, this expires in 1 hour.
ghs_knjVAQQVgpez6y4x6iBtm1BPkCLTlv33Zryn
Both tokens return tokenType as oauth
The documentation for @octokit/auth-app is not clear on how to disable expiry.
SDK Version
3.388.0
API Version
No response
Relevant log output
No response
Code of Conduct
- [X] I agree to follow this project's Code of Conduct
👋 Hi! Thank you for this contribution! Just to let you know, our GitHub SDK team does a round of issue and PR reviews twice a week, every Monday and Friday! We have a process in place for prioritizing and responding to your input. Because you are a part of this community please feel free to comment, add to, or pick up any issues/PRs that are labled with Status: Up for grabs. You & others like you are the reason all of this works! So thank you & happy coding! 🚀
Your code does not create a user-to-server token. What exactly is your use case?
You user-to-server token can only be created using the web flow or the device flow. The Device flow needs to be enabled in the app in order for it to work.
The installation token approach produces a token such as this. However, this expires in 1 hour.
ghs_knjVAQQVgpez6y4x6iBtm1BPkCLTlv33Zryn
Installation access tokens always expire after one hour. But if you pass the strategy to an Octokit constructor it will renew the token for you.
- User has Github App installed on account/org during account on-boarding.
- User create a service CI/CD pipeline without a Personal Access Token (not possible in our use case)
- The Application creates a token that does not expire in order for the pipeline to keep watching the repos for changes.
- The App also periodically regenerates the tokens on behalf of the User, as best practice suggests.
Would you be kind enough to update the documentation or respond with sample code on how to generate a user-to-server token without expiry?
how to generate a
user-to-servertoken
you cannot generate a user-to-server token, it would mean to authenticate as a user through a GitHub App. User involvement is required for that flow, usually an OAuth web flow
It sounds like a common use case, I'd usually use an action like this to create an installation access token based on app credentials: https://github.com/gr2m/github-app-token-action and then use the resulting token in successive steps. However that token expires after one hour.
For cases where a token is needed for tasks that take more than an hour, the tasks themselves need to accept the GitHub App credentials and create installation access tokens as needed
User involvement is required for that flow, usually an OAuth web flow
- User selects a repo (using installation token), clicks Continue
- Popup/Redirect to Github OAuth web flow (confirms permissions over selected repo)
- Return to page (with the
codeparameter)
At this point, we can create a user-to-server token without expiry for further use?
yeah that should work. Note that user-to-server token expiration is a setting on the github app ("Optional features" tab in app settings)