Library / SDK
18F/identity-idp avatar
18F/identity-idp

identity-idp is the Rails codebase behind Login.gov

Login.gov Core App: Identity Provider (IdP)

593 stars166 forksRubyNOASSERTION

At a glance

What is it?
This repository holds the core identity management system powering secure.login.gov, a Rails application with a TypeScript and webpack front end, and almost none of its documentation is in the README. What the repository does show is the shape of the work: a Makefile with around fifty targets covering lint, security auditing and test splitting, GitLab CI files for deployment, and a package.json that lints its own OpenAPI document.
Who is it for?
identity-idp fits a federal identity engineer or a civic tech developer who wants to work on a real large scale identity provider, and it does not fit a team that wants a reusable authentication component, since this is an application for a specific service rather than a library.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The README is generated, which tells you where the documentation lives

The repository contains the core code base and documentation for the identity management system powering secure.login.gov, which is the public's one account for government, used for secure and private access to participating government agencies.

The README is very short, and it says why. It is auto-generated, and running make README.md regenerates its contents, so the file is a pointer rather than a narrative. That is a deliberate choice for a project where the documentation has a lifecycle of its own, and it tells you where to look instead.

The documentation index is the substance of the README. There is a local development guide for setting up your environment, a back-end architecture document and a front-end architecture document, a mobile local development guide, a security document, a troubleshooting guide for local development, a document on A/B testing, and a guide for upgrading and A/B testing the Acuant SDK. The contributing guide covers pull requests, commit messages and the code review process, and the Login.gov Handbook is described as describing organisational practices, including process runbooks and team structures.

Two of those links are worth calling out. The handbook describes how the teams work, which for an open source project is unusual and unusually useful, and the SDK upgrade guide tells you that a third party identity verification SDK is swapped out and A/B tested against the current one, which is a real operational practice rather than a hypothetical one.

The project is a Rails application, with Ruby as the primary language and a TypeScript front end, and the homepage is the live service.

The Makefile is the real interface to the project

A Rails application with a separate front end build has a lot of commands, and this project refuses to make developers remember them. The Makefile exists for that purpose, and its own comment explains that recipes longer than one or two lines should live in script files in the bin directory.

The targets are grouped by verb, and the help output is generated by a Ruby parser at lib/makefile_help_parser.rb, so make help lists everything without a second list to maintain.

bash
help: ## Show this help
all: check
setup $(CONFIG): config/application.yml.default ## Runs setup scripts (updates packages, dependencies, databases, etc)
check: lint test ## Runs lint tests and spec tests

The setup target runs bin/setup, which is where the dependency, package and database setup actually lives, and check runs lint and then the spec tests. The configuration file is config/application.yml, generated from config/application.yml.default, and the server defaults to localhost on port 3000 with a HOST and PORT override.

The most interesting group is the lint family, and the list of names is a good description of what a government identity project worries about. Alongside the usual erb_lint, rubocop, yaml and openapi linting there are targets for linting analytics events, tracker events, country dialling codes, database schema files, font glyphs, lockfiles, new TypeScript files, optimised assets, asset bundle size, the README and spec file names. There is also a lint_openapi target, a normalize_yaml target, an optimize_svg target, a build_artifact target that produces a tarball at tmp/idp.tar.gz, and an urn target whose purpose the Makefile does not explain.

The front end build is a workspace with its own linters and test runner

The package.json describes a Node front end that is managed as a workspace, with the workspaces field pointing at app/javascript/packages, and the package name is @18f/identity-idp with a private flag and a version of 0.0.1. The engines require Node 22 or newer and npm 10 or newer, and the repository has an .nvmrc and a .ruby-version for the Ruby side.

The scripts show the shape of the build. There is a typecheck that runs tsc, a lint that runs eslint over JavaScript, JSX, TypeScript, TSX and the CommonJS and module variants, a separate lint for CSS that runs stylelint over the stylesheets and the component styles, and a lint for the OpenAPI document that runs redocly against the attempts API spec in docs/attempts-api/openapi.yml. Linting the API specification is not common, and it is a reasonable thing for a service whose clients are other agencies.

Tests run under mocha, with the spec pattern covering both the spec/javascript directory and the specs inside the packages workspaces. The build compiles with webpack and runs make browsers.json in parallel with it, the CSS is built by build-sass from a list of entry stylesheets, and several steps use concurrently to run two tasks at once. There is a script to generate the browsers JSON from a script in the scripts directory, a clean target that removes the built packs, and a postinstall that runs a postinstall step inside the @18f/identity-analytics workspace.

The configuration files at the root match that list: an .eslintrc, an .eslintignore, a .stylelintrc.json, a .prettierrc, a .browserslistrc, a .npmrc, a babel.config.js, a tsconfig.json and a svgo.config.js for SVG optimisation.

Security tooling is a first class part of the build

The repository root contains a set of files that a normal application project does not have, and together they describe the security posture of the project.

There is a .secrets.baseline file, which is the record of a secret scanning tool and the check that fails when new secrets appear. There is a .bundler-audit.yml, which is the configuration for checking the Ruby dependencies against known vulnerabilities, and a .snyk file for the same purpose on the JavaScript side. The Makefile has an audit target and a brakeman target, and Brakeman is the static analyser for Ruby on Rails applications that looks for common Rails security mistakes.

Then there is a directory called pwned_passwords, which suggests the service checks user passwords against a known breached password list rather than only against its own policy, and a directory of pwned_passwords data files that ships with the repository.

The credential handling is visible too. There are certs.example/ and keys.example/ directories, which is a pattern where the example files are committed and the real certificates and keys are supplied by the environment, and a .envrc for the development environment. The .irbrc file configures the interactive Ruby console, and the .erb_lint.yml, .rubocop.yml and .stylelintrc.json hold the style configuration.

The security document is in the docs directory rather than in the root, and the SECURITY.md file is listed in the documentation index, which is the place a reporter would look for the disclosure process.

Deployment through GitLab CI, with a development environment pinned by Nix

The continuous integration setup is spread across several GitLab CI files in the repository root, and the names indicate the separation of concerns:.gitlab-ci.yml for the main pipeline,.gitlab-ci-deploy.yml for deployment,.gitlab-ci-devenv.yml for the development environment, and.gitlab-ci-rules.yml for the rule definitions. GitLab rather than GitHub Actions, which is notable for a project of this kind, and the.github/ directory is also present for the workflows that do run there.

The container story is in the deploy/ directory, the dockerfiles/ directory, the production.Dockerfile at the root and a.dockerignore. A Procfile sits alongside them, which is the convention for declaring the process types a Heroku-style deployment runs, and the Makefile's build_artifact target produces a tarball artefact, which is the kind of artefact a deployment pipeline would consume.

The development environment is reproducible. There is a devenv.nix, a devenv.yaml and a devenv.lock, so the toolchain is pinned by Nix rather than by whatever a developer has installed, and a Brewfile for the macOS side of that. A Rakefile and a config.ru are the Ruby entry points, and the config directory holds the application configuration, including the application.yml file the Makefile generates.

The test suite is split rather than run as one long job. There is a knapsack_rspec_report.json at the root, which is the record of how the RSpec suite is divided across parallel workers, and the Makefile has a plain test target. For a project of this size, splitting the suite is what keeps the feedback loop short.

Release candidates with a counter, and a repository that is the product

The release naming is unusual and worth understanding before you plan an upgrade.

The published releases are named with a timestamp and an RC number: 2026-10-15T175108 with RC 619, 2026-10-13T203545 with RC 618, and 2026-10-08T182541 with RC 617. So the version is the moment the build was made plus a monotonically increasing release candidate counter, and there is no semantic version to compare. For a service deployed continuously, that is a reasonable scheme, since what you want to know is which build is running, but it means you cannot express a dependency constraint in the usual way.

The last push was on 2026-10-20, five days after the newest release candidate, and the repository is not archived.

The licence is recorded as a custom one that GitHub cannot classify, with a LICENSE.md at the root. The project is government software, and the appropriate reading of the terms is the file itself.

The last thing to understand is what this repository is not. It is not a library and not a component you can drop into a product. It is the application behind a specific service, with its own feature flags, its own A/B testing machinery, its own document verification SDK, and its own operational runbooks. The documentation index even has a page for upgrading and A/B testing the SDK, which tells you the dependency is swapped out regularly behind a flag. If you want to add a feature to a public identity provider, this is the code you work in, and the cost of that work is measured in the process described in the handbook, not in the pull request.

Editorial conclusion

identity-idp fits a federal identity engineer or a civic tech developer who wants to work on a real large scale identity provider, and it does not fit a team that wants a reusable authentication component, since this is an application for a specific service rather than a library. Before you start, read the local development guide and the backend and frontend architecture documents, because the README itself is auto-generated and points nowhere else, and note that the release tags are timestamped release candidates with an RC counter, so there is no semantic version to pin. The last push was on 2026-10-20 and the repository is not archived.

Frequently asked questions

What is the 18F/identity-idp repository?

It contains the core code base and documentation for the identity management system powering secure.login.gov, the Login.gov identity provider. The primary language is Ruby and it is a Rails application with a TypeScript and webpack front end.

How do I set up a local development environment for identity-idp?

The README points to the local development document in the docs directory, and the Makefile setup target runs bin/setup, which updates packages, dependencies and databases. The configuration is generated from config/application.yml.default into config/application.yml, and the server listens on localhost port 3000 by default.

What does the identity-idp Makefile help target do?

It lists the available targets using a Ruby help parser at lib/makefile_help_parser.rb, so the list of commands is generated from the Makefile itself. There are around fifty targets covering setup, linting, tests, building an artefact and repository housekeeping.

How are the identity-idp releases versioned?

The release names are timestamps with a release candidate counter, for example 2026-10-15T175108 with RC 619. There is no semantic version, and the last push was on 2026-10-20 with the repository not archived.

Official sources

  1. 18F/identity-idp on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/18f-identity-idp.svg)](https://hysenlabs.com/projects/18f-identity-idp)