{"id":15713679,"url":"https://github.com/azutoolkit/authly","last_synced_at":"2025-07-04T17:10:14.173Z","repository":{"id":46257648,"uuid":"227887293","full_name":"azutoolkit/authly","owner":"azutoolkit","description":"OAuth2 Provider Library - Authly is an OAuth2 Library for creating Authorization Servers that follows OAuth2 authorization mechanisms.","archived":false,"fork":false,"pushed_at":"2024-10-19T14:03:11.000Z","size":4833,"stargazers_count":30,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-07T21:45:18.493Z","etag":null,"topics":["authorization","crystal","crystal-lang","oauth2","provider","shard"],"latest_commit_sha":null,"homepage":"","language":"Crystal","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/azutoolkit.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,"zenodo":null}},"created_at":"2019-12-13T17:08:13.000Z","updated_at":"2025-01-19T21:29:05.000Z","dependencies_parsed_at":"2024-10-24T10:52:05.515Z","dependency_job_id":"2d948ee7-46c4-42ab-ac94-22f7d3c8327c","html_url":"https://github.com/azutoolkit/authly","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/azutoolkit/authly","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azutoolkit%2Fauthly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azutoolkit%2Fauthly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azutoolkit%2Fauthly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azutoolkit%2Fauthly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/azutoolkit","download_url":"https://codeload.github.com/azutoolkit/authly/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azutoolkit%2Fauthly/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263585897,"owners_count":23484488,"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":["authorization","crystal","crystal-lang","oauth2","provider","shard"],"created_at":"2024-10-03T21:32:53.167Z","updated_at":"2025-07-04T17:10:14.139Z","avatar_url":"https://github.com/azutoolkit.png","language":"Crystal","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Authly - Simplify Authentication for Your Application\n\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/747eef2e02594d40b63c9f05c6b94cd9)](https://app.codacy.com/manual/eliasjpr/authly?utm_source=github.com\u0026utm_medium=referral\u0026utm_content=eliasjpr/authly\u0026utm_campaign=Badge_Grade_Settings) [![Crystal CI](https://github.com/azutoolkit/authly/actions/workflows/crystal.yml/badge.svg?branch=master)](https://github.com/azutoolkit/authly/actions/workflows/crystal.yml)\n\n\u003cdiv style=\"text-align:center\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/azutoolkit/authly/master/authly.png\" /\u003e\u003c/div\u003e\n\nAuthly is an open-source Crystal library that helps developers integrate secure and robust authentication capabilities into their applications with ease. Supporting various OAuth2 grants and providing straightforward APIs, Authly aims to streamline the process of managing authentication in a modern software environment.\n\n## Table of Contents\n\n- [Authly - Simplify Authentication for Your Application](#authly---simplify-authentication-for-your-application)\n  - [Table of Contents](#table-of-contents)\n  - [About The Project](#about-the-project)\n  - [Getting Started](#getting-started)\n    - [Prerequisites](#prerequisites)\n    - [Installation](#installation)\n  - [Usage](#usage)\n    - [Configuration Setup](#configuration-setup)\n    - [Custom Authorizable Client and Owner](#custom-authorizable-client-and-owner)\n      - [Custom Client Example](#custom-client-example)\n      - [Custom Owner Example](#custom-owner-example)\n    - [Creating a Custom TokenStore](#creating-a-custom-tokenstore)\n      - [Custom TokenStore Example](#custom-tokenstore-example)\n    - [OAuth2 Grants](#oauth2-grants)\n    - [Endpoints](#endpoints)\n    - [Example Usage](#example-usage)\n  - [Features](#features)\n  - [Roadmap](#roadmap)\n  - [Contributing](#contributing)\n  - [License](#license)\n  - [Contact](#contact)\n  - [Acknowledgments](#acknowledgments)\n\n## About The Project\n\nAuthly is designed to make authentication simple for developers who want to focus on building their application rather than getting bogged down in authentication logic. Authly offers:\n\n- Support for OAuth2 grant types, including Authorization Code, Client Credentials, Password, Implicit, Device Code, and Refresh Token.\n- OpenID Connect support for ID Token generation.\n- A well-documented, intuitive API.\n- Built-in token management with support for introspection and revocation.\n- Easy-to-configure HTTP handlers for integrating authentication flows.\n- Support for both opaque and JWT tokens.\n\n## Getting Started\n\nTo get started with Authly, follow these steps to install and integrate it with your project.\n\n### Prerequisites\n\n- Crystal language (v1.0 or higher)\n- A working development environment (Linux, macOS, or Windows)\n\n### Installation\n\nTo install Authly, add it to your `shard.yml`:\n\n```yaml\ndependencies:\n  authly:\n    github: azutoolkit/authly\n```\n\nRun `shards install` to add the dependency to your project.\n\n## Usage\n\n### Configuration Setup\n\nTo configure Authly, you need to set up some essential configuration options for your application. These options include issuer information, secret keys, token expiration settings, and custom handlers. Here’s how you can set up the configuration:\n\n```crystal\nAuthly.configure do |config|\n  config.issuer = \"https://your-app.com\"\n  config.secret_key = ENV[\"AUTHLY_SECRET_KEY\"] # Ensure you keep this key secure\n  config.public_key = ENV[\"AUTHLY_PUBLIC_KEY\"]\n  config.refresh_ttl = 1.day # Token Time-to-Live in seconds\n  config.code_ttl = 5.minutes\n  config.access_ttl =1.hour\n  config.owners = CustomAuthorizableOwner.new\n  config.clients = CustomAuthorizableClient.new\n  config.token_store = CustomTokenStore.new\n  config.algorithm = JWT::Algorithm::HS256\n  config.token_strategy = :jwt\nend\n```\n\nThis configuration ensures that your application has secure, well-defined settings for token management.\n\n### Custom Authorizable Client and Owner\n\nAuthly allows you to implement custom clients and owners to define how they are authorized within your application. You need to implement `AuthorizableClient` and `AuthorizableOwner` interfaces.\n\n#### Custom Client Example\n\n```crystal\nclass CustomAuthorizableClient\n  include Authly::AuthorizableClient\n\n  def valid_redirect?(redirect_uri : String) : Bool\n    # Implement logic to verify if the provided redirect URI is valid\n    valid_uris = [\"https://your-app.com/callback\", \"https://another-allowed-url.com\"]\n    valid_uris.includes?(redirect_uri)\n  end\n\n  def authorized?(client_id : String, client_secret : String) : Bool\n    # Implement logic to verify client credentials\n    client_id == \"expected_client_id\" \u0026\u0026 client_secret == \"expected_client_secret\"\n  end\nend\n```\n\n#### Custom Owner Example\n\n```crystal\nclass CustomAuthorizableOwner\n  include Authly::AuthorizableOwner\n\n  def authorized?(username : String, password : String) : Bool\n    # Implement logic to verify user credentials\n    username == \"valid_user\" \u0026\u0026 password == \"valid_password\"\n  end\n\n  def id_token(user_data : Hash(String, String)) : String\n    # Create an ID Token for the user\n    \"user_id_token\"\n  end\nend\n```\n\nThese implementations allow your app to customize the logic for verifying clients and owners.\n\n### Creating a Custom TokenStore\n\nAuthly comes with an in-memory token store by default, which works well for development or single-node deployments. However, for production use or when you need persistence across restarts, you can create a custom `TokenStore`.\n\n#### Custom TokenStore Example\n\n```crystal\nclass CustomTokenStore\n  include Authly::TokenStore\n\n  def store(token : String, data : Hash(String, String))\n    # Store token in a database or any other persistent storage\n    DB.exec(\"INSERT INTO tokens (token, data) VALUES (?, ?)\", token, data.to_json)\n  end\n\n  def fetch(token : String) : Hash(String, String)?\n    # Fetch token data from the persistent storage\n    result = DB.query_one(\"SELECT data FROM tokens WHERE token = ?\", token)\n    result.not_nil! ? JSON.parse(result, Hash(String, String)) : nil\n  end\n\n  def revoke(token : String)\n    # Revoke a token by removing it from the persistent storage\n    DB.exec(\"DELETE FROM tokens WHERE token = ?\", token)\n  end\n\n  def revoked?(token : String) : Bool\n    # Check if a token has been revoked\n    !DB.query_one(\"SELECT 1 FROM tokens WHERE token = ?\", token).nil?\n  end\n\n  def valid?(token : String) : Bool\n    # Implement logic to verify if the token is still valid\n    !revoked?(token)\n  end\nend\n```\n\nThis custom store allows for better scalability and persistence, making your authentication system robust and reliable.\n\n### OAuth2 Grants\n\nAuthly supports several OAuth2 grant types, which can be used based on your application's authentication needs:\n\n1. **Authorization Code Grant**: This is the most secure grant type, typically used by server-side applications where the client secret can be kept confidential. It involves an intermediate authorization code that is exchanged for an access token.\n2. **Implicit Grant**: This grant type is used for public clients, such as JavaScript apps, where the access token is returned directly without an intermediate authorization code.\n3. **Resource Owner Credentials Grant**: Suitable for highly trusted applications, this grant type allows the use of the resource owner's username and password directly to obtain an access token.\n4. **Client Credentials Grant**: Used when the client itself is the resource owner, or when accessing its own resources. This is suitable for machine-to-machine communication.\n5. **Refresh Token Grant**: Allows clients to obtain a new access token without requiring user interaction, thus improving the user experience by keeping users logged in.\n6. **Device Code**: Suitable for devices that have limited input capabilities. The device code flow allows users to authenticate on a separate device with a browser.\n\nEach of these grants can be accessed through the `/oauth/token` endpoint, with specific parameters to specify the grant type.\n\nAuthly provides an easy way to set up an authentication service in your application. Here's how to get started with its key components:\n\n### Endpoints\n\nAuthly provides HTTP handlers to set up OAuth2 endpoints. The available endpoints include:\n\n1. **Authorization Endpoint** (`/oauth/authorize`): Used to get authorization from the resource owner.\n\n   ```crystal\n   server = HTTP::Server.new([\n     Authly::Handler.new,\n   ])\n   server.bind_tcp(\"127.0.0.1\", 8080)\n   server.listen\n   ```\n\n2. **Token Endpoint** (`/oauth/token`): Used to exchange an authorization grant for an access token.\n3. **Introspection Endpoint** (`/introspect`): Allows clients to validate the token.\n4. **Revoke Endpoint** (`/revoke`): Used to revoke an access or refresh token.\n\n### Example Usage\n\nTo integrate Authly into your existing application, create an instance of the server with the appropriate handlers:\n\n```crystal\nrequire \"authly\"\n\nserver = HTTP::Server.new([\n  Authly::Handler.new,\n])\nserver.bind_tcp(\"0.0.0.0\", 8080)\nputs \"Listening on http://0.0.0.0:8080\"\nserver.listen\n```\n\nOnce the server is running, you can send HTTP requests to authenticate users and manage tokens.\n\n## Features\n\n- **OAuth2 Grants**:\n  - [x] Authorization Code Grant\n  - [x] Implicit Grant\n  - [x] Resource Owner Credentials Grant\n  - [x] Client Credentials Grant\n  - [x] Refresh Token Grant\n  - [x] Device Code\n- **OpenID Connect (ID Token)**: Generate ID tokens for user identity.\n- **Token Introspection**: Allows clients to validate tokens.\n- **Token Revocation**: Easy-to-use token revocation functionality to invalidate access or refresh tokens.\n- **Opaque Tokens**: Support for opaque tokens in addition to JWTs.\n- **Configurable Handlers**: Customizable HTTP handlers to integrate authentication endpoints into your application effortlessly.\n\n## Roadmap\n\n- [ ] Add more examples for integrating with front-end frameworks.\n- [ ] Support OpenID Connect for extended authentication features.\n- [ ] Add more customization options for token storage backends.\n\nSee the [open issues](https://github.com/yourusername/authly/issues) for a list of proposed features (and known issues).\n\n## Contributing\n\nContributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.\n\n1. Fork the Project\n2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the Branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n## License\n\nDistributed under the MIT License. See `LICENSE` for more information.\n\n## Contact\n\nElias J. Perez - [@eliasjpr](https://github.com/eliasjpr)\nProject Link: [https://github.com/yourusername/authly](https://github.com/yourusername/authly)\n\n## Acknowledgments\n\n- [Best-README-Template](https://github.com/othneildrew/Best-README-Template)\n- [Readme Best Practices](https://github.com/jehna/readme-best-practices)\n- [Shields.io](https://shields.io) for the beautiful badges\n- [GitHub Pages](https://pages.github.com) for hosting project documentation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fazutoolkit%2Fauthly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fazutoolkit%2Fauthly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fazutoolkit%2Fauthly/lists"}