diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 86d167d..f71c0cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,7 @@ on: jobs: code-quality: + name: Code Quality runs-on: ubuntu-latest strategy: matrix: @@ -24,6 +25,7 @@ jobs: run: pdm run ruff check --diff testing: + name: Testing runs-on: ubuntu-latest strategy: matrix: diff --git a/.github/workflows/release_to_pypi.yml b/.github/workflows/release_to_pypi.yml new file mode 100644 index 0000000..4a9c57c --- /dev/null +++ b/.github/workflows/release_to_pypi.yml @@ -0,0 +1,16 @@ +name: Release + +on: + release: + types: [published] + +jobs: + pypi-publish: + name: upload release to PyPI + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pdm-project/setup-pdm@v4 + - name: Publish package distributions to PyPI + run: | + pdm publish --password ${{ secrets.PYPI_API_TOKEN }} diff --git a/.gitignore b/.gitignore index 3a8816c..f394764 100644 --- a/.gitignore +++ b/.gitignore @@ -160,3 +160,6 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ + +# custom +prompt.md diff --git a/README.md b/README.md index 3c780bc..eef0c7a 100644 --- a/README.md +++ b/README.md @@ -1 +1,235 @@ # SimpleSocialAuthLib + +SimpleSocialAuthLib is a Python library designed to simplify social authentication for various providers. It offers a straightforward interface for handling OAuth2 flows and retrieving user data from popular social platforms. + +## Contents + +- [Why use SimpleSocialAuthLib?](#why-use-simplesocialauthlib) +- [Installation](#installation) +- [Configuration](#configuration) +- [Usage](#usage) +- [Returned Data Structure and OAuth URLs](#returned-data-structure-and-oauth-urls) +- [Full Example](#full-example) +- [Contributing](#contributing) +- [License](#license) + +## Why use SimpleSocialAuthLib? + +- **Simplicity**: Offers a clean and intuitive API for social authentication. +- **Flexibility**: Supports multiple social providers with a consistent interface. +- **Type Safety**: Utilizes Python type hints for better code quality and IDE support. +- **Extensibility**: Easily add new social providers by extending the base classes. + +## Supported Social Providers + +- [x] Google +- [x] GitHub + +## Installation + +Install SimpleSocialAuthLib: + +```bash +# using pip +pip install simplesocialauthlib + +# using pdm +pdm add simplesocialauthlib + +# using uv +uv add simplesocialauthlib +``` + +## Configuration + +Before using SimpleSocialAuthLib, you need to set up your social provider credentials. Here's how to configure for Google and GitHub: + +### Google + +1. Go to the [Google Cloud Console](https://console.cloud.google.com/). +2. Create a new project or select an existing one. +3. Enable the Google+ API. +4. Create OAuth 2.0 credentials (client ID and client secret). +5. Set up the authorized redirect URIs. + +### GitHub + +1. Go to your [GitHub Developer Settings](https://github.com/settings/developers). +2. Click on "New OAuth App". +3. Fill in the application details, including the callback URL. +4. Once created, you'll get a client ID and can generate a client secret. + +## Usage + +Here's a basic example of how to use SimpleSocialAuthLib with Google authentication: + +```python +from simplesocialauthlib.providers.google import GoogleSocialAuth + +# Initialize the Google auth provider +google_auth = GoogleSocialAuth( + client_id="your_google_client_id", + client_secret="your_google_client_secret", + redirect_uri="your_redirect_uri" +) + +# After receiving the code from Google's OAuth redirect +code = "received_authorization_code" + +# Complete the sign-in process +user_data = google_auth.sign_in(code=code) + +# Use the user data as needed +print(f"Welcome, {user_data['full_name']}!") +``` + +## Returned Data Structure and OAuth URLs + +### Google + +**OAuth URL**: +``` +https://accounts.google.com/o/oauth2/v2/auth?redirect_uri={{ GOOGLE_REDIRECT_URI }}&prompt=consent&response_type=code&client_id={{ GOOGLE_CLIENT_ID }}&scope=openid%20email%20profile&access_type=offline +``` + +**User Data Structure**: +```python +class GoogleUserData(TypedDict): + first_name: str + last_name: str + full_name: str + email: str + email_verified: bool + picture: str | None +``` + +### GitHub + +**OAuth URL**: +``` +https://github.com/login/oauth/authorize/?client_id={{ GITHUB_CLIENT_ID }} +``` + +**User Data Structure**: +```python +class GithubUserData(TypedDict): + username: str + full_name: str + email: str + picture: str | None + bio: str | None + location: str | None +``` + +## Full Example + +Here's a full example using Flask to implement social login with both Google and GitHub: + +```python +# app.py + +import os +import logging + +from flask import Flask, request, redirect, flash, render_template +from dotenv import load_dotenv + +from simplesocialauthlib.providers.google import GoogleSocialAuth +from simplesocialauthlib.providers.github import GithubSocialAuth + +load_dotenv() +logging.basicConfig(level=logging.INFO) + +app = Flask(__name__) +app.secret_key = os.environ["SECRET_KEY"] + + +@app.route("/login") +def login(): + return render_template( + "login.html", + GOOGLE_CLIENT_ID=os.environ["GOOGLE_CLIENT_ID"], + GOOGLE_REDIRECT_URI=os.environ["GOOGLE_REDIRECT_URI"], + GITHUB_CLIENT_ID=os.environ["GITHUB_CLIENT_ID"], + ) + + +@app.route("/login/google") +def sign_in_with_google(): + code = request.args.get("code") + if not code: + return redirect("/login") + + try: + google_auth = GoogleSocialAuth( + client_id=os.environ["GOOGLE_CLIENT_ID"], + client_secret=os.environ["GOOGLE_CLIENT_SECRET"], + redirect_uri=os.environ["GOOGLE_REDIRECT_URI"] + ) + user_data = google_auth.sign_in(code=code) + # Process user_data (e.g., create/update user in your database) + flash("You are now signed in with Google.", category="success") + return redirect("/") + except Exception as e: + logging.error(e) + flash("Something went wrong. Please try again.", category="danger") + return redirect("/login") + + +@app.route("/login/github") +def sign_in_with_github(): + code = request.args.get("code") + if not code: + return redirect("/login") + + try: + github_auth = GithubSocialAuth( + client_id=os.environ["GITHUB_CLIENT_ID"], + client_secret=os.environ["GITHUB_CLIENT_SECRET"] + ) + user_data = github_auth.sign_in(code=code) + # Process user_data (e.g., create/update user in your database) + flash("You are now signed in with Github.", category="success") + return redirect("/") + except Exception as e: + logging.error(e) + flash("Something went wrong. Please try again.", category="danger") + return redirect("/login") + + +if __name__ == "__main__": + app.run(debug=True) +``` + +```html + + +... + +
+ + + Login with Google + + + + + Login with Github + +
+ +... + +``` + +## Contributing + +Contributions to SimpleSocialAuthLib are welcome! Please feel free to submit a Pull Request. + +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. diff --git a/pyproject.toml b/pyproject.toml index 44f3492..a3a29f9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,19 +1,20 @@ [project] name = "SimpleSocialAuthLib" dynamic = ["version"] -description = "SimpleSocialAuthLib is a lightweight and easy-to-use Python library that simplifies OAuth2 authentication integration with social providers such as Google, GitHub, Facebook, Twitter, and more." +description = "SimpleSocialAuthLib is a Python library designed to simplify social authentication for various providers. It offers a straightforward interface for handling OAuth2 flows and retrieving user data from popular social platforms." authors = [ {name = "Macktireh", email = "abdimack97@gmail.com"}, ] readme = "README.md" license = {text = "MIT"} classifiers = [ - "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.12", + "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Intended Audience :: Developers", + "Typing :: Typed", "Topic :: Software Development :: Libraries" ] requires-python = ">=3.12" @@ -22,13 +23,18 @@ dependencies = [ "requests-oauthlib>=2.0.0", ] +[project.urls] +Homepage = "https://github.com/Macktireh/SimpleSocialAuthLib" +Documentation = "https://github.com/Macktireh/SimpleSocialAuthLib#readme" +Repository = "https://github.com/Macktireh/SimpleSocialAuthLib" +Issues = "https://github.com/Macktireh/SimpleSocialAuthLib/issues" + [tool.pdm] distribution = true [tool.pdm.version] -source = "file" -path = "src/simplesocialauthlib/__init__.py" +source = "scm" [tool.pdm.dev-dependencies] lint = [ @@ -53,10 +59,6 @@ url = "https://mirror.sjtu.edu.cn/pypi/web/simple" name = "sjtug" -[tool.mypy] -ignore_missing_imports = true - - [tool.ruff] line-length = 130 exclude = [ diff --git a/requirements/lint.txt b/requirements/lint.txt index 5014f9b..b4a2191 100644 --- a/requirements/lint.txt +++ b/requirements/lint.txt @@ -1,4 +1,2 @@ -mypy pre-commit ruff -types-requests diff --git a/src/simplesocialauthlib/__init__.py b/src/simplesocialauthlib/__init__.py index 3dc1f76..e69de29 100644 --- a/src/simplesocialauthlib/__init__.py +++ b/src/simplesocialauthlib/__init__.py @@ -1 +0,0 @@ -__version__ = "0.1.0" diff --git a/src/simplesocialauthlib/types.py b/src/simplesocialauthlib/types.py index 1d238db..1b034be 100644 --- a/src/simplesocialauthlib/types.py +++ b/src/simplesocialauthlib/types.py @@ -4,7 +4,7 @@ class GoogleUserData(TypedDict): first_name: Annotated[str, "Corresponds to 'given_name' in Google API"] last_name: Annotated[str, "Corresponds to 'family_name' in Google API"] - full_name: Annotated[str | None, "Corresponds to 'name' in Google API"] + full_name: Annotated[str, "Corresponds to 'name' in Google API"] email: Annotated[str, "Corresponds to 'email' in Google API"] email_verified: Annotated[bool, "Corresponds to 'email_verified' in Google API"] picture: Annotated[str | None, "Corresponds to 'picture' in Google API"]