# FastAPI Reference

## [Installation](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#installation)
```bash
pip install propelauth_fastapi
```

## [Initialize](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#initialize)
`init_auth` performs a one-time initialization of the library. It will verify your `api_key` is correct and fetch the metadata needed to verify access tokens in [require_user](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#require-user) or [optional_user](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#optional-user).

In serverless environments, it's beneficial to skip the fetch, in which case you can pass in `token_verification_metadata` instead of having the library fetch it. You can find your verifier key and issuer URL in the **Backend Integration** page in your PropelAuth dashboard.

### Traditional
```py
from propelauth_fastapi import init_auth

auth = init_auth("YOUR_AUTH_URL", "YOUR_API_KEY")
```

### Serverless
```py
from propelauth_fastapi import init_auth_async

auth = init_auth_async(
    "YOUR_AUTH_URL",
    "YOUR_API_KEY",
    httpx_client=httpx.AsyncClient() # Optional. Only needed if you want to use a custom client
)
```

# Protect API Routes

Protecting an API route is as simple as adding a [dependency](https://fastapi.tiangolo.com/tutorial/dependencies/) to your route. None of the dependencies make an external request to PropelAuth. They all are verified locally using the [access token](https://docs.propelauth.com/recipes/access-tokens) provided in the request, making it very fast.

## [require_user](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#require-user)
A dependency that will verify the request was made by a valid user. If a valid [access token](https://docs.propelauth.com/recipes/access-tokens) is provided, it will return a [User](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#user) object. If not, the request is rejected with a 401 status code.

```py
from fastapi import FastAPI, Depends
from propelauth_fastapi import init_auth, User

app = FastAPI()
auth = init_auth("AUTH_URL", "API_KEY")

@app.get("/")
async def root(current_user: User = Depends(auth.require_user)):
    return {"message": f"Hello {current_user.user_id}"}
```

## [optional_user](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#optional-user)
Similar to [require_user](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#require-user), but will return `None` if no valid access token is provided.

```py
from typing import Optional

from fastapi import FastAPI, Depends
from propelauth_fastapi import init_auth, User

app = FastAPI()
auth = init_auth("AUTH_URL", "API_KEY")

@app.get("/api/whoami_optional")
async def whoami_optional(current_user: Optional[User] = Depends(auth.optional_user)):
    if current_user:
        return {"user_id": current_user.user_id}
    return {}
```

# Authorization / Organizations

You can also verify which organizations the user is in, and which roles and permissions they have in each organization all through the [User](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#user) or [OrgMemberInfo](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#org-member-info) objects.

## [Check Org Membership](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#check-org-membership)
Verify that the request was made by a valid user **and** that the user is a member of the specified organization. This can be done using the [User](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#user) object.

```py
@app.get("/api/org/{org_id}")
async def org_membership(org_id: str, current_user: User = Depends(auth.require_user)):
    org = current_user.get_org(org_id)
    if org == None:
        raise HTTPException(status_code=403, detail="Forbidden")
    return f"You are in org {org.org_name}"
```

## [Check Org Membership and Role](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#check-org-membership-and-role)
Similar to checking org membership, but will also verify that the user has a specific Role in the organization. This can be done using either the [User](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#user) or [OrgMemberInfo](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#org-member-info) objects.

A user has a Role within an organization. By default, the available roles are Owner, Admin, or Member, but these can be configured. These roles are also hierarchical, so Owner > Admin > Member.

```py
@app.get("/api/org/{org_id}")
def org_owner(org_id: str, current_user: User = Depends(auth.require_user)):
    org = current_user.get_org(org_id)
    if (org == None) or (org.user_is_role("Owner") == False):
        raise HTTPException(status_code=403, detail="Forbidden")
    return f"You are an Owner in org {org.org_name}"
```

## [Check Org Membership and Permission](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#check-org-membership-and-permission)
Similar to checking org membership, but will also verify that the user has the specified permission in the organization. This can be done using either the [User](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#user) or [OrgMemberInfo](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#org-member-info) objects.

Permissions are arbitrary strings associated with a role. For example, `can_view_billing`, `ProductA::CanCreate`, and `ReadOnly` are all valid permissions. You can create these permissions in the PropelAuth dashboard.

```py
@app.get("/api/org/{org_id}")
def org_billing(org_id: str, current_user: User = Depends(auth.require_user)):
    org = current_user.get_org(org_id)
    if (org == None) or (org.user_has_permission("can_view_billing") == False):
        raise HTTPException(status_code=403, detail="Forbidden")
    return Response(f"You can view billing information for org {org.org_name}")
```

## [User](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#user)
The User object contains information about the user that made the request.

- `user_id`: The unique id of the user.
- `org_id_to_org_member_info`: A dictionary mapping from organization id to [OrgMemberInfo](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#org-member-info) object.
- `email`: The email of the user.
- `first_name`: The first name of the user.
- `last_name`: The last name of the user.
- `username`: The username of the user.
- `properties`: A dictionary of [custom properties](https://docs.propelauth.com/overview/user-management/user-properties#custom-user-properties) associated with the user.
- `legacy_user_id`: If the user was migrated using our [Migration API](https://docs.propelauth.com/migrations), this will be the id of the user in the legacy system.
- `impersonator_user_id`: If the user is being impersonated, this is id of the user that impersonated them.
- `active_org_id`: Returns the ID of the [Active Org](https://docs.propelauth.com/recipes/active-org), if the user has an Active Org set.
- `login_method`: The method the user used to log in.
- `is_impersonated()`: True if the user is being impersonated.
- `get_active_org()`: Returns the [OrgMemberInfo](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#org-member-info) of the [Active Org](https://docs.propelauth.com/recipes/active-org), if the user has an Active Org set.
- `get_active_org_id()`: Returns the ID of the [Active Org](https://docs.propelauth.com/recipes/active-org), if the user has an Active Org set.
- `get_org(org_id)`: Returns the org member info for the org_id, if the user is in the org.
- `get_org_by_name(org_name)`: Returns the org member info for the org_name, if the user is in the org.
- `get_user_property(property_name)`: Returns the user property value, if it exists.
- `get_orgs()`: Returns the orgs the user is in.
- `is_role_in_org(org_id, role)`: Returns true if the user is the role in the org.
- `is_at_least_role_in_org(org_id, role)`: Returns true if the user is at least the role in the org.
- `has_permission_in_org(org_id, permission)`: Returns true if the user has the permission in the org.
- `has_all_permissions_in_org(org_id, permissions)`: Returns true if the user has all the permissions in the org.

## [OrgMemberInfo](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#org-member-info)
The OrgMemberInfo object contains information about the user's membership in an organization.

- `org_id`: The unique id of the organization.
- `org_name`: The name of the organization.
- `org_metadata`: The metadata associated with the organization.
- `user_assigned_role`: The role of the user in the organization.
- `user_inherited_roles_plus_current_role`: The role of the user within this organization plus each inherited role.
- `user_permissions`: A list of permissions the user has in the organization, based on their role.
- `url_safe_org_name`: A URL-safe version of the org_name property.
- `user_is_role`: A function that returns true if the user has the specified role in the organization.
- `user_is_at_least_role`: A function that returns true if the user has at least the specified role in the organization.
- `user_has_permission`: A function that returns true if the user has the specified permission in the organization.
- `user_has_all_permissions`: A function that returns true if the user has all of the specified permissions in the organization.
- `org_role_structure`: The role structure set for your project.
- `assigned_additional_roles`: If using multiple roles per user, returns an array of roles that the user belongs to. Excludes the `user_assigned_role`.
- `legacy_org_id`: If the org was migrated from another system, this will be the ID of the org in the legacy system.

## [Usage with API Docs](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#usage-with-api-docs)
FastAPIs built in documentation will automatically add this button when you are using either require_user or optional_user.

## [Calling Backend APIs](https://docs.propelauth.com/reference/backend-apis/fastapi?ref=propelauth.mymidnight.blog#calling-backend-apis)
You can also use the library to call the PropelAuth APIs directly, allowing you to fetch users, create orgs, and a lot more.
