BadgeFed (aka ActivityPub Badges) is a minimalistic, federated badge system inspired by Credly, built with .NET and leveraging the ActivityPub protocol and the OpenBadges spec. It enables issuing, managing, and verifying digital badges across federated servers.
- Blog: badgefed.vocalcat.com
- Matrix: @badgefed:matrix.org
- Issue and manage digital badges and grants
- ActivityPub protocol support for federation (see implementation details)
- Built with .NET 9
- OAuth login (Mastodon, LinkedIn)
- Email notifications
- Easily extensible and self-hostable
- 100% Open Source under the LGPL license.
A list of public BadgeFed servers is maintained in SERVERS.md, generated from servers.json using the gen.sh script. To contribute a server, create a pull request in this repo by adding it to servers.json.
To run BadgeFed in a Docker container, follow these steps:
-
Build the Docker Image:
docker build -t badgefed src/
-
Run the Container (with persistence for data storage):
docker run -d -p 8080:8080 --name badgefed \ -v $(pwd)/badgefed/data:/app/data \ -v $(pwd)/badgefed/config:/app/config \ -v $(pwd)/badgefed/pages:/app/wwwroot/pages \ -e DB_DATA="/app/data" \ badgefed
A fully docker example would be:
docker run -d \
-p 5000:80 \
--name badgefed \
-e SQLITE_DB_FILENAME="badgefed.db" \
-e ASPNETCORE_ENVIRONMENT="Production" \
-e "AdminAuthentication__AdminUsers__0__Id=mapache@hachyderm.io" \
-e "AdminAuthentication__AdminUsers__0__Type=Mastodon" \
-v $(pwd)/data:/app/data \
badgefedFor more details, refer to the Microsoft Configuration Documentation about how to pass environment variables in a dotnet docker image.
See the USAGE.md file for a detailed usage guide, including badge management, grant workflow, recipient profiles, and more.
BadgeFed uses a layered configuration system in .NET, allowing settings to be defined in appsettings.json, appsettings.Development.json, environment variables, and other sources. Below is a detailed guide to the available settings and how to use them.
- Purpose: Configures the logging levels for the application.
- Location:
appsettings.jsonandappsettings.Development.json - Example:
"Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }
- Usage: Adjust the log levels to control the verbosity of logs. Common levels include
Information,Warning, andError.
- Purpose: Specifies the allowed hosts for the application.
- Location:
appsettings.jsonandappsettings.Development.json - Example:
"AllowedHosts": "*"
- Usage: Use
*to allow all hosts or specify a list of allowed domains.
- Purpose: Defines the domains used for badge issuance and verification.
- Location:
appsettings.jsonandappsettings.Development.json - Example:
"BadgesDomains": [ "badgefed.example.com", "localhost:5000" ]
- Usage: Update this setting with the domain(s) where your application is hosted.
- Purpose: Configures admin users and their authentication types.
- Location:
appsettings.jsonandappsettings.Development.json - Example:
"AdminAuthentication": { "AdminUsers": [ { "Id": "admin@example.com", "Type": "LinkedIn" }, { "Id": "username@mastodoninstance.com", "Type": "Mastodon" } ] }
- Usage: Add admin users with their IDs and authentication types (
LinkedInorMastodon). LinkedIn uses email as IDs, and Mastodon uses usernames. If only Mastodon users are specified or only LinkedIn users are specified, only the corresponding login button will appear. For example, if no Mastodon users are specified, the Mastodon login button will not appear.
- Purpose: Mastodon OAuth authentication is supported out-of-the-box.
- Location: No configuration required.
- Example: N/A
- Usage: Mastodon authentication works with any Mastodon server without requiring any configuration. The system automatically registers OAuth applications dynamically when users log in from their Mastodon instances. For more details about Mastodon authentication, visit the Mastodon Developer Documentation.
If you want to use your own pre-registered Mastodon OAuth application instead of the automatic dynamic registration, you can configure it in appsettings.json:
"MastodonConfig": {
"Server": "mastodon.social",
"ClientId": "your-client-id",
"ClientSecret": "your-client-secret"
}To register your own OAuth application on your Mastodon server:
- Go to your Mastodon instance's Preferences > Development > New Application
- Set the required scopes:
read,read:accounts, andprofile - Set the redirect URI to:
https://your-badgefed-domain/signin-mastodon-dynamic - Copy the Client ID and Client Secret to your configuration
Note: When MastodonConfig is configured, the specified server will be pre-selected in the login dropdown. If only AdminAuthentication with Mastodon users is configured (without MastodonConfig), the dropdown will appear but without a pre-selected server, allowing users to choose or enter their server.
- Purpose: Configures LinkedIn OAuth for authentication.
- Location:
Program.cs(viaLinkedInConfigclass) - Example:
"LinkedInConfig": { "ClientId": "your-client-id", "ClientSecret": "your-client-secret" }
- Usage: Add Linked credentials in the configuration file or environment variables. You need to create a LinkedIn app with OpenId auth scope. For more details, visit the LinkedIn Developer Documentation.
- Purpose: Configures SMTP settings for sending emails.
- Location:
appsettings.jsonandappsettings.Development.json - Example:
"EmailSettings": { "SmtpServer": "smtp.example.com", "Port": 587, "SenderEmail": "noreply@example.com", "SenderName": "BadgeFed", "Username": "smtp-username", "Password": "smtp-password" }
- Usage: Update the SMTP server, port, sender email, and credentials for email functionality.
If you are using a reverse proxy, you need to make sure that your original host gets forwarded and that your WebSockets upgrades are properly handled. An example configuration for nginx below:
location / {
proxy_pass https://example.com;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
}For a technical overview of how BadgeFed implements ActivityPub and OpenBadge 2.0, see FEDERATION.md.
Contributions are welcome! To add a new server, update servers.json and run gen.sh.
For code contributions, please open an issue or submit a pull request.
This project is licensed under the LGPL License. See the LICENSE file for details.