{"id":17037966,"url":"https://github.com/kzu/githubfunctions","last_synced_at":"2026-05-02T18:41:46.841Z","repository":{"id":223337821,"uuid":"759856297","full_name":"kzu/GitHubFunctions","owner":"kzu","description":"A GitHub-authenticated Azure Functions app","archived":false,"fork":false,"pushed_at":"2024-04-11T22:35:19.000Z","size":68,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-24T07:27:49.425Z","etag":null,"topics":["azure","azure-functions","dotnet","github"],"latest_commit_sha":null,"homepage":"https://ghauth.azurewebsites.net/me","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kzu.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"devlooped"}},"created_at":"2024-02-19T13:19:19.000Z","updated_at":"2024-03-02T20:20:27.000Z","dependencies_parsed_at":"2024-11-29T15:32:35.349Z","dependency_job_id":"52e05945-f745-4fe6-a164-b2671b241a05","html_url":"https://github.com/kzu/GitHubFunctions","commit_stats":null,"previous_names":["kzu/auth0functions","kzu/githubfunctions"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kzu/GitHubFunctions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kzu%2FGitHubFunctions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kzu%2FGitHubFunctions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kzu%2FGitHubFunctions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kzu%2FGitHubFunctions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kzu","download_url":"https://codeload.github.com/kzu/GitHubFunctions/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kzu%2FGitHubFunctions/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262685118,"owners_count":23348409,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure","azure-functions","dotnet","github"],"created_at":"2024-10-14T08:55:36.005Z","updated_at":"2026-05-02T18:41:41.800Z","avatar_url":"https://github.com/kzu.png","language":"C#","funding_links":["https://github.com/sponsors/devlooped"],"categories":[],"sub_categories":[],"readme":"# GitHub authentication for Azure Functions\n\nThis sample showcases a functions app that can use GitHub authentication \nconfigured via the Azure Portal, with support for both API-based and \nweb-based authentication flows.\n\n## Getting started\n\n1. Fork this repo\n2. Create a [new function app](https://portal.azure.com/#create/Microsoft.FunctionApp) in the Azure Portal. \n   \u003e For simplicity, use the consumption plan and ensure .NET and Windows are used for runtime/plan,\n   \u003e .NET 8, isolated worker model.\n\n   Note the function app's URL\n3. Create a [new GitHub OAuth app](https://github.com/settings/applications/new)\n   a. Set the \"Authorization callback URL\" to the function app's URL with the path `/.auth/login/github/callback`\n\n   Note the app's Client ID and generate a new Client Secret\n\n4. Back in the Azure Portal, configure GitHub login as explained in the \n   [Azure docs](https://learn.microsoft.com/en-us/azure/app-service/configure-authentication-provider-github)\n   \u003e Make sure to select `Allow unauthenticated users`, otherwise the CLI/API access will not work.\n   \u003e Leave `Token store` checked.\n \n5. Finally, deploy from your fork. For simplicity, I choose the App Service Build Service to deploy the function app.\n\nNavigate to the function app's URL plus `/me` to invoke the function. You should be redirected to GitHub to sign in,\nand then see your GitHub user info in the browser rendered as JSON.\n\nYou can try it out at https://ghauth.azurewebsites.net/me\n\n## Local development\n\nYou can run the function app locally, but you won't be able to replicate the web-based authentication flow, \nsince the callback URL in the GitHub app will not match your production deployment. This a limitation on the \nGH app side (Auth0 does allow multiple callback URLs, for example). In addition, the function app running \nlocally, does not have the plumbing to handle the web-based auth flow that is provided by the Azure App Service.\n\nIn order to work around this, the functions app is configured to perform an API-based device flow and store \nthe access token as a cookie in the browser. The way to make this work is as follows:\n\n1. Add a secret containing the Client ID from the GitHub app by running this command in the function app's \n   directory:\n\n   ```shell\n   dotnet user-secrets set \"GitHub:ClientId\" \"your-client-id\"\n   ```\n\n2. Run the functions app and watch the console for the device code and URL to authenticate with. \n   The console will render the device code and URL to authenticate with. While you do this manually,     \n   the current function invocation will pause execution. If you take too long, it's possible for the \n   function execution to timeout.\n\nOnce you authenticate, the token will be saved in a cookie and subsequent calls will use it to authenticate.\nThe rest of the flow will work just as in the case of the API/CLI-based device flow.\n\n\nYou can test the API/CLI-based device flow, as follows:\n\n1. Set both the console and the functions app as startup projects.\n2. Run with F5 (with debugger). This is what causes the console app to use localhost rather than the \n   production URL.\n3. The console will prompt for the client ID and perform the device flow auth. Copy the device code that \n   will be rendered in the console and paste it in the browser window that will open.\n4. Once autenticated, the credentials will be saved using the GCM-powered \n   [credential store](https://github.com/devlooped/CredentialManager/) and subsequent calls will verify \n   the saved token and use it to authenticate with the function app.\n\n\n## Notes\n\nThe function app highlights how to perform a web-based authentication flow by detecting anonymous requests \nand redirecting just like the `Require authenticated user` setting does. A pair of function middleware \nclasses take care of populating the claims in both scenarios so that the function app can depend generically \non just the `ClaimsFeature` that's added to the `FunctionContext.Features`.\n\nThe sample also showcases leveraging the `ClaimsPrincipal.ClaimsPrincipalSelector` to set the \nauthenticated user automatically so that functions can basically just depend on `ClaimsPrincipal.Current` \nthroughout.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkzu%2Fgithubfunctions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkzu%2Fgithubfunctions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkzu%2Fgithubfunctions/lists"}