{"id":16009356,"url":"https://github.com/xyb/drf-passwordless-jwt","last_synced_at":"2025-10-30T01:14:23.167Z","repository":{"id":142247564,"uuid":"584437621","full_name":"xyb/drf-passwordless-jwt","owner":"xyb","description":"JWT passwordless auth service using Django REST framework","archived":false,"fork":false,"pushed_at":"2024-06-26T03:36:14.000Z","size":85,"stargazers_count":3,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-15T13:08:09.227Z","etag":null,"topics":["auth","authentication","django","django-rest-framework","docker","email","jwt","passwordless","python","restful-api","smtp"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xyb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-02T15:09:50.000Z","updated_at":"2024-06-25T05:58:01.000Z","dependencies_parsed_at":"2024-01-26T05:23:31.802Z","dependency_job_id":"63d46b5c-526b-4a4f-bc34-383fde187493","html_url":"https://github.com/xyb/drf-passwordless-jwt","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xyb%2Fdrf-passwordless-jwt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xyb%2Fdrf-passwordless-jwt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xyb%2Fdrf-passwordless-jwt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xyb%2Fdrf-passwordless-jwt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xyb","download_url":"https://codeload.github.com/xyb/drf-passwordless-jwt/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221699988,"owners_count":16866068,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auth","authentication","django","django-rest-framework","docker","email","jwt","passwordless","python","restful-api","smtp"],"created_at":"2024-10-08T13:01:42.334Z","updated_at":"2025-10-30T01:14:18.111Z","avatar_url":"https://github.com/xyb.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# drf-passwordless-jwt\n\n[![Test Status](https://github.com/xyb/drf-passwordless-jwt/actions/workflows/test.yml/badge.svg)](https://github.com/xyb/drf-passwordless-jwt/actions/workflows/test.yml)\n[![Test Coverage](https://api.codeclimate.com/v1/badges/246f7e7b16bb43588638/test_coverage)](https://codeclimate.com/github/xyb/drf-passwordless-jwt/test_coverage)\n\n`drf-passwordless-jwt` is a RESTful API service that offers passwordless\nauthentication using JWT. In other words, it's a Single Sign-On (SSO)\nservice that allows users to log in without using a password.\n\n## Features\n- Email login token\n- Obtain JWT token\n- Verify JWT token\n- Dummy accounts used for development and testing purposes.\n\n## Usage\n\n```sh\n# Email login token\n$ curl -X POST -d \"email=xyb@test.com\" localhost:8000/auth/email/\n{\"detail\":\"A login token has been sent to your email.\"}\n\nEnter this token to sign in: 527389\n\n# Obtain JWT token\n$ curl -X POST -d \"email=xyb@test.com\u0026token=527389\" localhost:8000/auth/jwt/\n{\"token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Inh5YkB0ZXN0LmNvbSIsImV4cCI6MTY3NTI2Njg0NH0.a7RgJLEbeFSQeFZ93qjC2iHo_wabglwzBZ9fe9D-rfw\",\"email\":\"xyb@test.com\"}\n\n# Verify JWT token\n$ curl -X POST -d \"token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Inh5YkB0ZXN0LmNvbSIsImV4cCI6MTY3NTI2Njg0NH0.a7RgJLEbeFSQeFZ93qjC2iHo_wabglwzBZ9fe9D-rfw\" \\\n  localhost:8000/auth/\n{\"email\":\"xyb@test.com\",\"exp\":\"2023-02-01T15:54:04Z\"}\n\n# or verify via http header\n$ curl -X GET -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Inh5YkB0ZXN0LmNvbSIsImV4cCI6MTY3NTI2Njg0NH0.a7RgJLEbeFSQeFZ93qjC2iHo_wabglwzBZ9fe9D-rfw\" \\\n  localhost:8000/auth/header/\n{\"email\":\"xyb@test.com\",\"exp\":\"2023-02-01T15:54:04Z\"}\n\n# or verify via http cookie\n$ curl -X GET --cookie \"Authorization=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Inh5YkB0ZXN0LmNvbSIsImV4cCI6MTY3NTI2Njg0NH0.a7RgJLEbeFSQeFZ93qjC2iHo_wabglwzBZ9fe9D-rfw\" \\\n  localhost:8000/auth/header/\n{\"email\":\"xyb@test.com\",\"exp\":\"2023-02-01T15:54:04Z\"}\n```\n\nIt uses [Django REST framework](https://www.django-rest-framework.org/),\nso you can also access this interface through your browser.\n\n![](drf.webp)\n\n## Dummy accounts\n\nDuring development and testing, you may want to use dummy accounts to\nsave time. To do this, you can configure environment variables.\nFor example, if you want to use the email address a@a.com to log in,\nyou can set the environment variable:\n```sh\n$ export EMAIL_TEST_ACCOUNT_a_at_a_com=123456\n```\n\nThen, you can use the command:\n```sh\n$ curl -X POST -d \"email=a@a.com\u0026token=123456\" localhost:8000/auth/jwt/\n```\n\nto directly obtain a JWT token without having to first obtain a login\ntoken via email. This way, you can cut out the step of first getting\na login token via email, and immediately receive a JWT token.\nThis hack could save you significant time.\n\n## Configuration\n\nYou should customize your configuration to suit your requirements.\nAll configurations can be set via environment variables.\nThe following are the configured default values:\n\n```python\n# 0: production, 1: development\nDJANGO_DEBUG = 1\n\n# specify hosts separated by commas\nDJANGO_ALLOWED_HOSTS = '*'\n\n# 1: print email to screen, not sending\nEMAIL_BACKEND_TEST = 0\n\n# email from\nOTP_EMAIL_ADDRESS = 'No Reply \u003cxyb@mydomain.com\u003e'\n\n# token expire time, default 5 minutes\nOTP_TOKEN_EXPIRE_SECONDS = 300\n\n# email subject\nOTP_EMAIL_SUBJECT = 'Your Login Token'\n\n# email text message\nOTP_EMAIL_PLAINTEXT = 'Enter this code to sign in: %s'\n\n# email html message template file\n# set it to 'passwordless_zh_token_email.html' to use the built-in Chinese template.\nOTP_EMAIL_HTML = 'passwordless_token_email.html'\n\n# the http header name if you like to pass token via http header\n# it's useful when setup this as a forward auth service\n# for API gateway like using APISIX forward-auth plugin.\nAUTH_HEADER_NAME = 'Authorization'\n\n# verify via http cookie name as a forward auth service\nAUTH_COOKIE_NAME = 'Authorization'\n\n# 1: ssl smtp\nEMAIL_USE_SSL = 0\n\n# 1: tls smtp\nEMAIL_USE_TLS = 0\n\nEMAIL_HOST = 'smtp.mydomain.com'\n\nEMAIL_HOST_USER = 'xyb@mydomain.com'\n\nEMAIL_HOST_PASSWORD = 'password'\n\nEMAIL_PORT = 465\n\nEMAIL_FROM = 'xyb@mydomain.com'\n\n# fail if smtp server response too slow\nEMAIL_TIMEOUT = 3\n\n# regex, for example: '.*@mail1.com$|.*@mail2.com'\nEMAIL_WHITE_LIST = r'.*'\n\n# message on rejection\nEMAIL_WHITE_LIST_MESSAGE = 'unacceptable email address'\n\n# dummy account env prefix\nEMAIL_TEST_ACCOUNT_PREFIX = 'EMAIL_TEST_ACCOUNT_'\n\n# specify hosts separeated by commas\nCORS_ALLOWED_ORIGINS = ''\n\n# 1: accept any remote host\nCORS_ALLOW_ALL_ORIGINS = 0\n\nDB_ENGINE = 'django.db.backends.sqlite3'\n\nDB_NAME = BASE_DIR / 'db.sqlite3'\n\nDB_USER = 'postgres'\n\nDB_PASSWORD = ''\n\nDB_HOST = ''\n\nDB_PORT = ''\n\n# JWT secret string\nJWT_SECRET = 'secret-for-jwt'\n\n# JWT expire time, default 30 days\nJWT_EXPIRE_SECONDS = 2592000\n```\n\n## Docker\n\nDuring development, you can build and run it on your local host:\n\n```sh\n$ docker build -t auth .\n$ docker run --rm -p 8000:8000 -e EMAIL_BACKEND_TEST=1 auth\n```\n\nThere are pre-built [docker images](https://hub.docker.com/r/xieyanbo/drf-passwordless-jwt).\nYou can use docker-compose for deployment.\nThis is a template of `docker-compose.yml`:\n\n```yaml\nversion: \"3\"\n\nservices:\n  auth:\n    image: xieyanbo/drf-passwordless-jwt:latest\n    container_name: auth\n    environment:\n      - TZ=Asia/Hong_Kong\n      - DJANGO_SECRET_KEY=secret-string\n      - DJANGO_DEBUG=0\n      - OTP_EMAIL_ADDRESS=\"No Reply \u003cxyb@mydomain.com\u003e\"\n      - OTP_TOKEN_EXPIRE_SECONDS=300\n      - OTP_EMAIL_SUBJECT=Your Login Token\n      - OTP_EMAIL_PLAINTEXT=Enter this code to sign in: %s\n      - OTP_EMAIL_HTML=passwordless_token_email.html\n      - EMAIL_BACKEND_TEST=0\n      - EMAIL_USE_SSL=0\n      - EMAIL_USE_TLS=1\n      - EMAIL_HOST=smtp.mydomain.com\n      - EMAIL_PORT=465\n      - EMAIL_HOST_USER=xyb@mydomain.com\n      - EMAIL_HOST_PASSWORD=password\n      - EMAIL_FROM=xyb@mydomain\n      - EMAIL_WHITE_LIST=.*@mydomain.com$$|.*@mydomain2.com$$\n      - EMAIL_WHITE_LIST_MESSAGE=for mydomain.com and mydomain2.com only\n      - JWT_SECRET=secret-for-jwt\n      - JWT_EXPIRE_SECONDS=2592000\n    ports:\n      - 8000:8000\n    restart: always\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxyb%2Fdrf-passwordless-jwt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxyb%2Fdrf-passwordless-jwt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxyb%2Fdrf-passwordless-jwt/lists"}