oauth2-cli-auth 2.0.0
Authenticate against OAuth2 Provider in Python CLIs
License: MIT
Requires Python: >=3.10

oauth2-cli-auth
===
[![LICENSE](https://img.shields.io/github/license/timo-reymann/python-oauth2-cli-auth)](https://github.com/timo-reymann/python-oauth2-cli-auth/blob/main/LICENSE)
[![CircleCI](https://circleci.com/gh/timo-reymann/python-oauth2-cli-auth.svg?style=shield)](https://app.circleci.com/pipelines/github/timo-reymann/python-oauth2-cli-auth)
[![GitHub Release](https://img.shields.io/github/v/tag/timo-reymann/python-oauth2-cli-auth?label=version)](https://github.com/timo-reymann/python-oauth2-cli-auth/releases)
[![PyPI version](https://badge.fury.io/py/oauth2-cli-auth.svg)](https://pypi.org/project/oauth2-cli-auth)
![PyPI - Downloads](https://img.shields.io/pypi/dm/oauth2-cli-auth)
[![codecov](https://codecov.io/gh/timo-reymann/python-oauth2-cli-auth/graph/badge.svg?token=zxY1pKcBaj)](https://codecov.io/gh/timo-reymann/python-oauth2-cli-auth)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=timo-reymann_python-oauth2-cli-auth&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=timo-reymann_python-oauth2-cli-auth)
[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=timo-reymann_python-oauth2-cli-auth&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=timo-reymann_python-oauth2-cli-auth)
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=timo-reymann_python-oauth2-cli-auth&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=timo-reymann_python-oauth2-cli-auth)
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=timo-reymann_python-oauth2-cli-auth&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=timo-reymann_python-oauth2-cli-auth)
[![Renovate](https://img.shields.io/badge/renovate-enabled-green?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNjkgMzY5Ij48Y2lyY2xlIGN4PSIxODkuOSIgY3k9IjE5MC4yIiByPSIxODQuNSIgZmlsbD0iI2ZmZTQyZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTUgLTYpIi8+PHBhdGggZmlsbD0iIzhiYjViNSIgZD0iTTI1MSAyNTZsLTM4LTM4YTE3IDE3IDAgMDEwLTI0bDU2LTU2YzItMiAyLTYgMC03bC0yMC0yMWE1IDUgMCAwMC03IDBsLTEzIDEyLTktOCAxMy0xM2ExNyAxNyAwIDAxMjQgMGwyMSAyMWM3IDcgNyAxNyAwIDI0bC01NiA1N2E1IDUgMCAwMDAgN2wzOCAzOHoiLz48cGF0aCBmaWxsPSIjZDk1NjEyIiBkPSJNMzAwIDI4OGwtOCA4Yy00IDQtMTEgNC0xNiAwbC00Ni00NmMtNS01LTUtMTIgMC0xNmw4LThjNC00IDExLTQgMTUgMGw0NyA0N2M0IDQgNCAxMSAwIDE1eiIvPjxwYXRoIGZpbGw9IiMyNGJmYmUiIGQ9Ik04MSAxODVsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzI1YzRjMyIgZD0iTTIyMCAxMDBsMjMgMjNjNCA0IDQgMTEgMCAxNkwxNDIgMjQwYy00IDQtMTEgNC0xNSAwbC0yNC0yNGMtNC00LTQtMTEgMC0xNWwxMDEtMTAxYzUtNSAxMi01IDE2IDB6Ii8+PHBhdGggZmlsbD0iIzFkZGVkZCIgZD0iTTk5IDE2N2wxOC0xOCAxOCAxOC0xOCAxOHoiLz48cGF0aCBmaWxsPSIjMDBhZmIzIiBkPSJNMjMwIDExMGwxMyAxM2M0IDQgNCAxMSAwIDE2TDE0MiAyNDBjLTQgNC0xMSA0LTE1IDBsLTEzLTEzYzQgNCAxMSA0IDE1IDBsMTAxLTEwMWM1LTUgNS0xMSAwLTE2eiIvPjxwYXRoIGZpbGw9IiMyNGJmYmUiIGQ9Ik0xMTYgMTQ5bDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMxZGRlZGQiIGQ9Ik0xMzQgMTMxbDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMxYmNmY2UiIGQ9Ik0xNTIgMTEzbDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMyNGJmYmUiIGQ9Ik0xNzAgOTVsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzFiY2ZjZSIgZD0iTTYzIDE2N2wxOC0xOCAxOCAxOC0xOCAxOHpNOTggMTMxbDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMzNGVkZWIiIGQ9Ik0xMzQgOTVsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzFiY2ZjZSIgZD0iTTE1MyA3OGwxOC0xOCAxOCAxOC0xOCAxOHoiLz48cGF0aCBmaWxsPSIjMzRlZGViIiBkPSJNODAgMTEzbDE4LTE3IDE4IDE3LTE4IDE4ek0xMzUgNjBsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzk4ZWRlYiIgZD0iTTI3IDEzMWwxOC0xOCAxOCAxOC0xOCAxOHoiLz48cGF0aCBmaWxsPSIjYjUzZTAyIiBkPSJNMjg1IDI1OGw3IDdjNCA0IDQgMTEgMCAxNWwtOCA4Yy00IDQtMTEgNC0xNiAwbC02LTdjNCA1IDExIDUgMTUgMGw4LTdjNC01IDQtMTIgMC0xNnoiLz48cGF0aCBmaWxsPSIjOThlZGViIiBkPSJNODEgNzhsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzAwYTNhMiIgZD0iTTIzNSAxMTVsOCA4YzQgNCA0IDExIDAgMTZMMTQyIDI0MGMtNCA0LTExIDQtMTUgMGwtOS05YzUgNSAxMiA1IDE2IDBsMTAxLTEwMWM0LTQgNC0xMSAwLTE1eiIvPjxwYXRoIGZpbGw9IiMzOWQ5ZDgiIGQ9Ik0yMjggMTA4bC04LThjLTQtNS0xMS01LTE2IDBMMTAzIDIwMWMtNCA0LTQgMTEgMCAxNWw4IDhjLTQtNC00LTExIDAtMTVsMTAxLTEwMWM1LTQgMTItNCAxNiAweiIvPjxwYXRoIGZpbGw9IiNhMzM5MDQiIGQ9Ik0yOTEgMjY0bDggOGM0IDQgNCAxMSAwIDE2bC04IDdjLTQgNS0xMSA1LTE1IDBsLTktOGM1IDUgMTIgNSAxNiAwbDgtOGM0LTQgNC0xMSAwLTE1eiIvPjxwYXRoIGZpbGw9IiNlYjZlMmQiIGQ9Ik0yNjAgMjMzbC00LTRjLTYtNi0xNy02LTIzIDAtNyA3LTcgMTcgMCAyNGw0IDRjLTQtNS00LTExIDAtMTZsOC04YzQtNCAxMS00IDE1IDB6Ii8+PHBhdGggZmlsbD0iIzEzYWNiZCIgZD0iTTEzNCAyNDhjLTQgMC04LTItMTEtNWwtMjMtMjNhMTYgMTYgMCAwMTAtMjNMMjAxIDk2YTE2IDE2IDAgMDEyMiAwbDI0IDI0YzYgNiA2IDE2IDAgMjJMMTQ2IDI0M2MtMyAzLTcgNS0xMiA1em03OC0xNDdsLTQgMi0xMDEgMTAxYTYgNiAwIDAwMCA5bDIzIDIzYTYgNiAwIDAwOSAwbDEwMS0xMDFhNiA2IDAgMDAwLTlsLTI0LTIzLTQtMnoiLz48cGF0aCBmaWxsPSIjYmY0NDA0IiBkPSJNMjg0IDMwNGMtNCAwLTgtMS0xMS00bC00Ny00N2MtNi02LTYtMTYgMC0yMmw4LThjNi02IDE2LTYgMjIgMGw0NyA0NmM2IDcgNiAxNyAwIDIzbC04IDhjLTMgMy03IDQtMTEgNHptLTM5LTc2Yy0xIDAtMyAwLTQgMmwtOCA3Yy0yIDMtMiA3IDAgOWw0NyA0N2E2IDYgMCAwMDkgMGw3LThjMy0yIDMtNiAwLTlsLTQ2LTQ2Yy0yLTItMy0yLTUtMnoiLz48L3N2Zz4=)](https://renovatebot.com)
[![pre-commit](https://img.shields.io/badge/%E2%9A%93%20%20pre--commit-enabled-success)](https://pre-commit.com/)

<p align="center">
	<img width="300" src="https://raw.githubusercontent.com/timo-reymann/python-oauth2-cli-auth/main/.github/images/logo.png">
    <br />
    Authenticate against OAuth2 Provider in Python CLIs
</p>

## Features

- Simple
- Fancy callback page

## Requirements

- Python 3.9+

## Installation

```sh
pip install oauth2-cli-auth
```

## Usage

### Simple with OIDC well known configuration endpoint

This should work for every provider supporting OIDC e.g. `gitlab.com`:

```python
from oauth2_cli_auth import get_access_token_with_browser_open, OAuth2ClientInfo

client_info = OAuth2ClientInfo.from_oidc_endpoint(
    "https://gitlab.com/.well-known/openid-configuration",
    client_id="my-client-id",
    scopes=["openid"]
)

try:
    token = get_access_token_with_browser_open(client_info)
    print(f"Obtained token '{token}'")
except ValueError:
    print("Failed to obtain token")
```

### Simple with manual endpoint specification

The following should work for almost all use cases, for rest please check the lib docs.

```python
from oauth2_cli_auth import get_access_token_with_browser_open, OAuth2ClientInfo

client_info = OAuth2ClientInfo(
    client_id="<clientId>",
    authorization_url="<authorizeUrl>",
    token_url="<TokenUrl>",
    scopes=["scopeA", "scopeB"]
)

try:
    token = get_access_token_with_browser_open(client_info)
    print(f"Obtained token '{token}'")
except ValueError:
    print("Failed to obtain token")
```

## Motivation

Building oauth2 integration for Python apps come quite handy, especially with Gitlab integration etc.

It is a bit cumbersome to do it manually everytime, existing solutions are way to overkill to put on this problem.
So I created this small library without any dependencies besides the python standard library.

## Documentation

- [Library documentation](https://timo-reymann.github.io/python-oauth2-cli-auth)

## Contributing

I love your input! I want to make contributing to this project as easy and transparent as possible, whether it's:

- Reporting a bug
- Discussing the current state of the configuration
- Submitting a fix
- Proposing new features
- Becoming a maintainer

To get started please read the [Contribution Guidelines](./CONTRIBUTING.md).

## Development

### Requirements

- Python 3.9+
- [pre-commit](https://pre-commit.com/)
- Poetry

### Test

```
poetry run pytest .
```

### Build

```sh
poetry install
```