Digital badge management for issuers, earners, and consumers
Badgr-server is the Python/Django API backend for issuing Open Badges. In addition to a powerful Issuer API and browser-based user interface for issuing, Badgr offers integrated badge management and sharing for badge earners. Free accounts are hosted by Concentric Sky at Badgr.com, but for complete control over your own issuing environment, Badgr Server is available open source as a Python/Django application.
See also badgr-ui, the front end written in Angular that serves as users' interface for this project.
Badgr was developed by Concentric Sky, starting in 2015 to serve as an open source reference implementation of the Open Badges Specification. It provides functionality to issue portable, verifiable Open Badges as well as to allow users to manage badges they have been awarded by any issuer that uses this open data standard. Since 2015, Badgr has grown to be used by hundreds of educational institutions and other people and organizations worldwide. See Project Homepage for more details about contributing to and integrating with Badgr.
Badgr-server hosts standard-compliant endpoints that implement the Open Badges 2.0 specification. For each of the core Open Badges objects Issuer, BadgeClass and Assertion, there is a standards-compliant public JSON endpoint handled by the Django application as well as an image redirect path.
Each JSON endpoint, such as /public/assertions/{entity_id}
, performs content negotiation. It will return a
standardized JSON-LD payload when the path is requested with no Accept
header or when JSON payloads are requested.
Additionally, User-Agent detection allows bots attempting to render a preview card for social sharing to access a clean
HTML response that includes Open Graph meta tags. Other clients requesting text/html
will receive
a redirect to the corresponding public route on the UI application that runs in parallel to Badgr-server where humans
can be presented with a representation of the badge data in their browser.
Each image endpoint typically redirects to an image within the associated storage system. The system can convert from SVG to PNG and adapt images to a common "wide" radio for the images needed for card-based previews in many social network systems.
Prerequisites:
Copy the example development settings:
cp .docker/etc/settings_local.dev.py.example .docker/etc/settings_local.dev.py
NOTE: you may wish to copy and edit the production config. See Running the Django Server in "Production" below for more details.
cp .docker/etc/settings_local.prod.py.example .docker/etc/settings_local.prod.py
Edit the settings_local.dev.py
and/or settings_local.prod.py
to adjust the following settings:
DEFAULT_FROM_EMAIL
to an address, for instance "noreply@localhost"
EMAIL_BACKEND= 'django.core.mail.backends.console.EmailBackend'
will log email content to console, which is often adequate for development. Other options are available. See Django docs for sending email.SECRET_KEY
and UNSUBSCRIBE_SECRET_KEY
each to (different) cryptographically secure random values.
python -c "import base64; import os; print(base64.b64encode(os.urandom(30)).decode('utf-8'))"
AUTHCODE_SECRET_KEY
to a 32 byte url-safe base64-encoded random string. This key is used for symmetrical encryption of authentication tokens. If not defined, services like OAuth will not work.
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key())"
Set or adjust these values in your settings_local.dev.py
and/or settings_local.prod.py
file to further configure the application to your specific needs.
HELP_EMAIL
:
help@badgr.io
.BADGR_APPROVED_ISSUERS_ONLY
:
True
, that means new user accounts will not be able to define new issuers (though they can be added as staff on issuers defined by others) unless they have the Django user permission 'issuer.add_issuer'. The recommended way to grant users this privilege is to create a group that grants it in the /staff
admin area and addthe appropriate users to that group.PINGDOM_MONITORING_ID
:
CELERY_ALWAYS_EAGER
:
True
causes Celery to immediately run tasks synchronously. Celery is an asynchronous task runner built into Django and Badgr. Advanced deployments may separate celery workers from web nodes for improved performance. For development environments where Celery tasks should run synchronously, set this flag to true. Very few time-intensive tasks are part of this repository, and eager is a safe setting for most production deploys.OPEN_FOR_SIGNUP
:
False
if you would like to use Badgr for only single-account use or to manually create all users in /staff
. The default is True
(signup API is enabled). UX is not well-supported in the /staff
interface.DEFAULT_FILE_STORAGE
and MEDIA_URL
:
NOUNPROJECT_API_KEY
and NOURNPROJECT_SECRET
:
AISKILLS_API_KEY
and AISKILLS_ENDPOINT
:
OIDC_RP_CLIENT_ID
and OIDC_RP_CLIENT_SECRET
OIDC_OP_AUTHORIZATION_ENDPOINT
, OIDC_OP_TOKEN_ENDPOINT
, OIDC_OP_USER_ENDPOINT
, OIDC_OP_JWKS_ENDPOINT
, OIDC_OP_END_SESSION_ENDPOINT
LOGIN_BASE_URL
http://localhost:4200/auth/login
LOGIN_REDIRECT_URL
and LOGOUT_REDIRECT_URL
auth/login?validateToken
urlhttp://localhost:4200/auth/login?validateToken
and http://localhost:4200/auth/login
LOGIN_BASE_URL
ALTCHA_API_KEY
and ALTCHA_SECRET
:
For development, it is usually best to run the project with the builtin django development server. The
development server will reload itself in the docker container whenever changes are made to the code in apps/
.
To run the project with docker in a development mode:
docker-compose up
: build and get django and other components runningdocker-compose exec api python /badgr_server/manage.py migrate
- (while running) set up database tablesdocker-compose exec api python /badgr_server/manage.py dist
- generate docs swagger file(s)docker-compose exec api python /badgr_server/manage.py collectstatic
- Put built front-end assets into the static directory (Admin panel CSS, swagger docs).docker-compose exec api python /badgr_server/manage.py createsuperuser
- follow prompts to create your first admin user accountBy default docker-compose
will look for a docker-compose.yml
for instructions of what to do. This file
is the development (and thus default) config for docker-compose
.
If you'd like to run the project with a more production-like setup, you can specify the docker-compose.prod.yml
file. This setup copies the project code in (instead of mirroring) and uses nginx with uwsgi to run django.
docker-compose -f docker-compose.prod.yml up -d
- build and get django and other components (production mode)
docker-compose -f docker-compose.prod.yml exec api python /badgr_server/manage.py migrate
- (while running) set up database tables
If you are using the production setup and you have made changes you wish to see reflected in the running container, you will need to stop and then rebuild the production containers:
docker-compose -f docker-compose.prod.yml build
- (re)build the production containers
If the extension urls aren't adjusted (or the url changes, or for some other reason it seems as if extension schemas can't be loaded, e.g. because of 401 errors in the badge creation process), run the script in scripts/change-extension-url.sh
.
To get the image on the prod server, simply update the release
branch and push it to github.
The rest should happen automatically (thanks to github actions and watchtower keeping the deployed image up to date).
The development server will be reachable on port 8000
:
The production server will be reachable on port 8080
:
There are various examples of URLs in this readme and they all feature the development port. You will need to adjust that if you are using the production server.
EmailAddress
object for your superuser. Edit your super userTermsVersion
objectIf your badgr-ui is running on http://localhost:4000, use the following values:
localhost:4000
http://localhost:4000/signup/
http://localhost:4000/auth/login/
http://localhost:4000/change-password/
http://localhost:4000/auth/login/
http://localhost:4000/signup/success/
http://localhost:4000/profile/
http://localhost:4000/public/
public
rw:profile rw:issuer rw:backpack
Badgr UI
If you set up the Additional configuration options (or at least the parts relevant for OIDC authentication), you shouldn't have to configure anything else; the "Anmelden mit Mein Bildungsraum" button should work out of the box. Do note that the OIDC authentication mechanism produces access tokens that, in contrast to the ones we generate ourselves, aren't restricted to any scopes. They can thus access anything on the page not limited to admin / superuser users. This also is the default behavior for the tokens we generate ourselves.
For the tests to run you first need to run docker (docker-compose up
).
Then within docker, run tox
: docker-compose exec api tox
.
Note that you might have to run docker-compose build
once for the new changes to the testing enviornment to take effect.
To just run a single test:
docker-compose exec api python /badgr_server/manage.py test -k <test-name>
# Example:
docker-compose exec api python /badgr_server/manage.py test issuer.tests.test_issuer.IssuerTests.test_cant_create_issuer_with_unverified_email_v1
For debugging, in the Docerfile.dev.api
debugpy
is also installed and there is the docker compose file docker-compose.debug.yml
.
In VSCode you can create a launch.json
by choosing Python
as debugger and Remote Attach
as debug configuration (and defaults for the rest).
You can then start the application with
docker compose -f docker-compose.yml -f docker-compose.debug.yml up
and attach the debugger in VSCode by selecting Python: Remote Attach. This process is heavily inspired by this tutorial.
Start in your badgr
directory and clone badgr-ui source code: git clone https://github.com/concentricsky/badgr-ui.git badgr-ui
For more details view the Readme for Badgr UI.
To ensure consistency and quality in code contributions, we use pre-commit hooks to adhere to commit message conventions and code quality guidelines. Follow these steps to set up your development environment:
Make sure you have pre-commit
installed on your machine. You can install it using pip:
pip install pre-commit
Navigate to the root directory of the repository and run the following command to initialize pre-commit hooks:
pre-commit install
This command sets up the pre-commit hooks defined in the pre-commit-config.yaml
file.
To run the configured hooks on some / all files of the project run:
pre-commit run --files <file-name>
pre-commit run --all-files
You will also need to have commitizen
installed, e.g. via
pip install commitizen