### Complete GitHub App Authentication Flow Source: https://context7.com/adriangodong/githubjwt/llms.txt This example demonstrates the full workflow of authenticating as a GitHub App installation using the generated JWT to obtain an installation access token, which is then used for API calls. ```csharp using GitHubJwt; using System; using System.Net.Http; using System.Net.Http.Headers; using System.Text.Json; using System.Threading.Tasks; public class GitHubAppAuthenticator { private readonly IGitHubJwtFactory _jwtFactory; private readonly HttpClient _httpClient; public GitHubAppAuthenticator(int appId, string privateKeyPath) { var options = new GitHubJwtFactoryOptions { AppIntegrationId = appId, ExpirationSeconds = 600 }; _jwtFactory = new GitHubJwtFactory( new FilePrivateKeySource(privateKeyPath), options); _httpClient = new HttpClient { BaseAddress = new Uri("https://api.github.com") }; _httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("MyGitHubApp/1.0"); _httpClient.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/vnd.github+json")); } public async Task GetInstallationTokenAsync(long installationId) { // Generate JWT for app authentication string jwt = _jwtFactory.CreateEncodedJwtToken(); // Use JWT to get installation access token var request = new HttpRequestMessage(HttpMethod.Post, $"/app/installations/{installationId}/access_tokens"); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", jwt); var response = await _httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); var json = await response.Content.ReadAsStringAsync(); var tokenResponse = JsonSerializer.Deserialize(json); return tokenResponse.GetProperty("token").GetString(); } public async Task GetRepositoryContentsAsync( long installationId, string owner, string repo) { string installationToken = await GetInstallationTokenAsync(installationId); var request = new HttpRequestMessage(HttpMethod.Get, $"/repos/{owner}/{repo}/contents"); request.Headers.Authorization = new AuthenticationHeaderValue("token", installationToken); var response = await _httpClient.SendAsync(request); return await response.Content.ReadAsStringAsync(); } } // Usage var authenticator = new GitHubAppAuthenticator( appId: 12345, privateKeyPath: "my-github-app.private-key.pem"); string contents = await authenticator.GetRepositoryContentsAsync( installationId: 98765, owner: "octocat", repo: "hello-world"); ``` -------------------------------- ### Load Private Key from File Source: https://context7.com/adriangodong/githubjwt/llms.txt Uses FilePrivateKeySource to read an RSA private key from a PEM-formatted file on disk. ```csharp using GitHubJwt; // Create a private key source that reads from a PEM file var privateKeySource = new FilePrivateKeySource("github-app.private-key.pem"); var options = new GitHubJwtFactoryOptions { AppIntegrationId = 6837, ExpirationSeconds = 600 }; var factory = new GitHubJwtFactory(privateKeySource, options); string token = factory.CreateEncodedJwtToken(); // The file should contain a full PEM-formatted RSA private key: // -----BEGIN RSA PRIVATE KEY----- // MIIEowIBAAKCAQEA... // -----END RSA PRIVATE KEY----- ``` -------------------------------- ### Load Private Key from Environment Variable Source: https://context7.com/adriangodong/githubjwt/llms.txt Uses EnvironmentVariablePrivateKeySource to retrieve a base64-encoded private key from an environment variable. ```csharp using GitHubJwt; using System; // Set environment variable with the private key (without PEM headers) // Example: GITHUB_APP_PRIVATE_KEY=MIIEowIBAAKCAQEA...base64content... Environment.SetEnvironmentVariable("GITHUB_APP_PRIVATE_KEY", "MIIEowIBAAKCAQEA2Z3qX2BTLS4e..."); // Create source that reads from the environment variable var privateKeySource = new EnvironmentVariablePrivateKeySource("GITHUB_APP_PRIVATE_KEY"); var options = new GitHubJwtFactoryOptions { AppIntegrationId = 6837, ExpirationSeconds = 600 }; var factory = new GitHubJwtFactory(privateKeySource, options); string token = factory.CreateEncodedJwtToken(); Console.WriteLine($"JWT from env var: {token}"); ``` -------------------------------- ### Load Private Key from String Source: https://context7.com/adriangodong/githubjwt/llms.txt Use StringPrivateKeySource when the private key is available as a string, such as from a secrets manager. Provide the key body without PEM headers. ```csharp using GitHubJwt; // Private key content (without PEM headers - they're added automatically) string privateKeyContent = "MIIEowIBAAKCAQEA2Z3qX2BTLS4eYKp..."; // You might load this from Azure Key Vault, AWS Secrets Manager, etc. // string privateKeyContent = await secretsClient.GetSecretAsync("github-app-key"); var privateKeySource = new StringPrivateKeySource(privateKeyContent); var options = new GitHubJwtFactoryOptions { AppIntegrationId = 6837, ExpirationSeconds = 600 }; var factory = new GitHubJwtFactory(privateKeySource, options); string token = factory.CreateEncodedJwtToken(); Console.WriteLine($"JWT from string: {token}"); ``` -------------------------------- ### Implement Custom Private Key Source Source: https://context7.com/adriangodong/githubjwt/llms.txt Implement the IPrivateKeySource interface for custom private key retrieval logic, such as from hardware security modules or encrypted files. The GetPrivateKeyReader method should return the full PEM format. ```csharp using GitHubJwt; using System.IO; // Custom implementation that loads from Azure Key Vault public class AzureKeyVaultPrivateKeySource : IPrivateKeySource { private readonly string _vaultUrl; private readonly string _secretName; public AzureKeyVaultPrivateKeySource(string vaultUrl, string secretName) { _vaultUrl = vaultUrl; _secretName = secretName; } public TextReader GetPrivateKeyReader() { // Retrieve the key from Azure Key Vault // var client = new SecretClient(new Uri(_vaultUrl), new DefaultAzureCredential()); // var secret = client.GetSecret(_secretName); // string keyContent = secret.Value.Value; string keyContent = "MIIEowIBAAKCAQEA..."; // Retrieved from vault // Return full PEM format return new StringReader( "-----BEGIN RSA PRIVATE KEY-----\n" + keyContent + "\n" + "-----END RSA PRIVATE KEY-----"); } } // Usage var keySource = new AzureKeyVaultPrivateKeySource( "https://mykeyvault.vault.azure.net/", "github-app-private-key"); var factory = new GitHubJwtFactory(keySource, new GitHubJwtFactoryOptions { AppIntegrationId = 12345, ExpirationSeconds = 600 }); string token = factory.CreateEncodedJwtToken(); ``` -------------------------------- ### Generate JWT Tokens with GitHubJwtFactory Source: https://context7.com/adriangodong/githubjwt/llms.txt Configures the factory with app ID and expiration, then generates a signed JWT token. Supports optional clock skew offsets. ```csharp using GitHubJwt; // Configure the factory with your GitHub App's ID and token expiration var options = new GitHubJwtFactoryOptions { AppIntegrationId = 12345, // Your GitHub App's ID ExpirationSeconds = 600 // Token validity (max 10 minutes per GitHub's requirements) }; // Create factory with a file-based private key source var privateKeySource = new FilePrivateKeySource("/path/to/your-app.private-key.pem"); var factory = new GitHubJwtFactory(privateKeySource, options); // Generate the JWT token string jwtToken = factory.CreateEncodedJwtToken(); // Use the token to authenticate with GitHub API // Authorization: Bearer Console.WriteLine($"Generated JWT: {jwtToken}"); // Optional: Apply an offset to the issued-at time (useful for clock skew) string tokenWithOffset = factory.CreateEncodedJwtToken(iatOffset: TimeSpan.FromSeconds(-60)); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.