# Quick start This tutorial builds a small Flask app with GitHub login, a callback, a profile route that calls GitHub, and logout. ## Before you start 1. [Install the package](installation.md). 2. [Create a GitHub OAuth App](installation.md#register-a-github-oauth-app). 3. Set its callback URL to `http://localhost:5000/callback`. For local development, provide the OAuth credentials and a Flask secret in your shell: ```console export SECRET_KEY="$(python -c 'import secrets; print(secrets.token_hex(32))')" export GITHUB_CLIENT_ID="your-oauth-app-client-id" export GITHUB_CLIENT_SECRET="your-oauth-app-client-secret" ``` The generated `SECRET_KEY` is for local development. Keep it stable while you use the app; changing it invalidates Flask's signed session cookies. For deployed applications, supply secrets through your platform's secret manager or environment configuration. ## Create `app.py` ```python import os import flask import flask_githubkit app = flask.Flask(__name__) app.config.from_mapping( SECRET_KEY=os.environ["SECRET_KEY"], GITHUB_CLIENT_ID=os.environ["GITHUB_CLIENT_ID"], GITHUB_CLIENT_SECRET=os.environ["GITHUB_CLIENT_SECRET"], GITHUB_REDIRECT_URI="http://localhost:5000/callback", GITHUB_SCOPE="read:user", ) github = flask_githubkit.GitHub(app) @app.route("/") def index(): return ( 'Sign in with GitHub ' 'View profile ' 'Sign out' ) @app.route("/login") @github.login def login(): """The decorator redirects to GitHub; this body is not called.""" @app.route("/callback") @github.callback def callback(access_token): if access_token is None: return "GitHub authorization was denied.", 401 return flask.redirect(flask.url_for("profile")) @app.route("/profile") def profile(): client = github.client() if client is None: return flask.redirect(flask.url_for("login")) user = client.rest.users.get_authenticated().parsed_data return flask.jsonify(login=user.login) @app.route("/logout") def logout(): github.logout() return flask.redirect(flask.url_for("index")) ``` ## Run the app From the directory containing `app.py`, start Flask: ```console flask --app app run ``` Open `http://localhost:5000/` and choose **Sign in with GitHub**. Completing the flow requires a working OAuth App and network access to GitHub. ```{note} On recent macOS versions, AirPlay Receiver can occupy port 5000. If Flask cannot bind to it, disable AirPlay Receiver or run on another port, and use the same port in `GITHUB_REDIRECT_URI` and the OAuth App's callback URL. ``` ## What happens during login 1. `@github.login` redirects the browser to GitHub and stores a random `state` value in the Flask session. 2. GitHub sends the browser back to `GITHUB_REDIRECT_URI` with an authorization code and the `state`. 3. `@github.callback` checks and consumes the `state`. If it is valid, the extension exchanges the code for a token, saves the token in the session, and calls `callback(access_token)`. 4. The profile route calls `github.client()`. The extension loads the session token and returns a GitHubKit client for the request. 5. GitHubKit refreshes an expired access token when the client is used. flask-githubkit saves the updated token values to the session after the request. The profile route does not need the `access_token` argument from the callback. The extension persists the token in the session so later routes can use `github.client()`. Prefer GitHubKit API methods over handling the raw token. ## Denied and invalid callbacks If the user denies authorization, the decorated callback view is called with `None`, allowing your app to show a message or redirect. A callback with missing or invalid `state` is rejected with HTTP 400 before the view runs. The one-time state value is consumed on the first callback attempt, so a replay is rejected. For application factories and Blueprints, see [complete examples](examples.md).