Skip to content

Commit

Permalink
Merge pull request #12 from Macktireh/develop
Browse files Browse the repository at this point in the history
update workflow CI and add a new workflow for release to PYPI
  • Loading branch information
Macktireh authored Sep 29, 2024
2 parents 91f8f75 + e839da3 commit 83319dc
Show file tree
Hide file tree
Showing 8 changed files with 266 additions and 12 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:

jobs:
code-quality:
name: Code Quality
runs-on: ubuntu-latest
strategy:
matrix:
Expand All @@ -24,6 +25,7 @@ jobs:
run: pdm run ruff check --diff

testing:
name: Testing
runs-on: ubuntu-latest
strategy:
matrix:
Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/release_to_pypi.yml
Original file line number Diff line number Diff line change
@@ -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 }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
234 changes: 234 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.html -->

...

<div class="d-grid gap-3 mx-auto" style="max-width: 320px;">
<!-- Google -->
<a
href="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"
>
<span>Login with Google</span>
</a>

<!-- Github -->
<a
href="https://github.com/login/oauth/authorize/?client_id={{ GITHUB_CLIENT_ID }}"
>
<span>Login with Github</span>
</a>
</div>

...

```

## 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.
18 changes: 10 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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 = [
Expand All @@ -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 = [
Expand Down
2 changes: 0 additions & 2 deletions requirements/lint.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
mypy
pre-commit
ruff
types-requests
1 change: 0 additions & 1 deletion src/simplesocialauthlib/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
__version__ = "0.1.0"
2 changes: 1 addition & 1 deletion src/simplesocialauthlib/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down

0 comments on commit 83319dc

Please sign in to comment.