Gatekeeper is an OIDC & OAuth2 server written in scala. This OAuth2 server is designed for the self-hosting community who are looking for an auth solution to get single sign-on on their self-hosted services.
Gatekeeper has been explicitly tested with the following services
- Jenkins (via the OpenId Connect Authentication Plugin)
- Portainer
- Gitea
However, if a service offers integration with a third party OAuth2 provider, there is a good chance Gatekeeper will work with it. If it doesn't, please raise an issue.
- Client registration
- Update Redirects
- Limit scopes
- Limit available OAuth2 flows
- Modify token validity
- Regenerate client Id and secret
- Create clients from presets
- User and developer registration
- Update email and password
- Email verification via
- AWS SES
- Mailgun
- More offerings to come
- TOTP MFA
- See list of apps accessing your account
- Revoke sessions for apps accessing your account
- Completely revoke access for apps accessing your account
- Grant types
- authorization_code
- client_credentials
- refresh_token
- Java 11
- Scala 2.13.3
- SBT 1.3.13
- MongoDB 4.2
- AWS credentials that have access to
- SES (Simple email service)
- SNS (Simple notification service)
We recommend managing Java, Scala and SBT via SDKMan. SDKMan installation notes can be found here.
Java, Scala and SBT can be installed with
sdk install java 11.0.11.hs-adpt (or whichever java 11 release is available at the time)
sdk install scala 2.13.6
sdk install sbt 1.5.3
For MongoDB, we recommend running MongoDB in docker. To boot a MongoDB image in docker, run
docker-compose -f docker-compose-mongo.yml up -d
To allow gatekeeper to send emails and sms messages you need an AWS account that has an IAM user or role available. AWS recommends creating IAM users and roles with the minimum set of privileges it needs to operate.
Create a policy with the following permissions and attach the policy to the IAM user or role.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GatekeeperMinPermissions",
"Effect": "Allow",
"Action": [
"ses:SendEmail",
"sns:Publish"
],
"Resource": "*"
}
]
}
On a new AWS Account, SES provides sandbox access. This means that you can only send emails to the Amazon SES mailbox simulator and verified email addresses or domains. You can request that AWS moves your account out of the SES sandbox, more details here.
sbt -Demail.from=test@email.com -Dplay.http.router=testing.Routes run
test@email.com should be replaced with a email address or domain that's been verified in AWS SES
This will start the application on port 5678
sbt compile test it:test
To the run the integration tests under it:test
you will need MongoDB running. Refer to the prerequesites section to understand how to boot MongoDB in docker.
The docker-boot.sh
file packages gatekeeper into a tgz to be used by the Dockerfile. Docker image is then built from the file and subsequently booted along with MongoDB from the docker-compose file.
Run ./docker-boot.sh
to run this process.
The following table describes what each of the gatekeeper envs means in the docker compose file.
Env Var | Default | Description |
---|---|---|
VERSION | dev | The version of Gatekeeper you're running. Appears at the bottom of pages |
EMAIL_FROM | test@email.com | The email address used to send emails from Gatekeeper |
MONGO_URI | mongodb://mongo.local | Where MongoDB lives. The database that backs Gatekeeper |
APP_SECRET | 23817cc7d0e6460e9c1515aa4047b29b | The app secret scala play uses to sign session cookies and CSRF tokens. Should be changed to run in prod |
ENC_KEY | 23817cc7d0e6460e9c1515aa4047b29b | The key used to secure data. Should be changed to run in prod |
WKC_ISSUER | http://localhost:5678 | Used in the tokens issued by Gatekeeper. Used in the token iss claim. Should be configured as the domain you connect to Gatekeeper with |
MFA_ISSUER | Gatekeeper (docker) | The string used to describe the TOTP Code in apps like Google Authenticator |
SMS_SENDER_ID | SmsVerify | The string used to say where SMS messages have come from |
EMAIL_PROVIDER | n/a | Used to determine what email provider to use. Valid options are ses or mail-gun |
AWS_REGION | n/a | Should only be set if EMAIL_PROVIDER is ses. Should match the AWS region you're running SES from |
AWS_IDENTITY_ARN | n/a | Should only be set if EMAIL_PROVIDER is ses. Should be the arn of the SES identity you're sending via if the SES identity lives in another AWS account |
MAILGUN_API_KEY | n/a | Should only be set if EMAIL_PROVIDER is mail-gun. Obtained from the mailgun console after account creation |
MAILGUN_URL | n/a | Should only be set if EMAIL_PROVIDER is mail-gun. Obtained from the mailgun console after account creation |
Gatekeeper currently sends emails via AWS SES or Mailgun. Both support sending emails from a proper address, or some address on a verified domain. On their respective free tiers you can only send to email addresses you've verified in SES or Mailgun. To lift that limitation you need to be on a paid plan. However, AWS SES lets you send 62000 emails a month for free forever, but you need to be in their production zone on SES. Mailgun, on their flex plan, allows 5000 emails a month for 3 months, and then you move to pay as you go ($0.80 / 1000 emails).
AWS SES allows AWS accounts to send email via verified identities from other accounts. More information can be found here.
Gatekeeper supports this if SES is your email provider. Ensure that the AWS_IDENTITY_ARN
env var is set to the arn you're wanting to send via.
That's a fair question. Neither may suit you. If you're technically minded, look at the adding more email providers section to find out more about adding your preferred provided (dev work required). If you're not technically minded, no fear, get started with a feature request and we can try to make your request a reality.
Find more information about each here
Gatekeeper supports creating client presets for
- Jenkins
- Grafana
- Portainer
- OpenId connect playground
OpenId connect playground has its domain configured as it's a managed service. Jenkins, grafana and portainer do not as they can be hosted anywhere.
well-known-services = [
{
name = "jenkins"
desc = "Build great things at any scale"
icon = "jenkins.svg"
redirect = "/securityRealm/finishLogin"
},
{
name = "openid connect playground"
desc = "For testing OIDC configurations"
icon = "openid.png"
domain = "https://openidconnect.net"
redirect = "/callback"
}
]
In application.conf
the well known services block defines the presets. You can extend the preset services by creating PR's that add to this list. The domain should be specified if the service is hosted in one place.
For the time being, the service's icon needs to be hosted in Gatekeeper, find a suitable image for the service and place the image in public/images/services
. In the config block enter the name of the file under icon.
Once a service has been added to this list, it will be available for creation in the frontend.
Right now Gatekeeper can send emails via AWS SES or Mailgun, however these providers can be extended. Below details how you can go about adding new email providers.
-
Clone the repository and branch off as
feature/email-provider/new-provider-name
-
Add the new email providers config into
conf/application.conf
email-service {
selected-provider = ${?EMAIL_PROVIDER}
message-settings {
from = ${?EMAIL_FROM}
verification-subject = "Verifying your account"
}
ses {
region = ${?AWS_REGION}
cross-account-identity-arn = ${?AWS_IDENTITY_ARN}
}
mail-gun {
api-key = ${?MAILGUN_API_KEY}
url = ${?MAILGUN_URL}
}
new-provider-name {
...whatever config the new provider needs. API Key, endpoints etc
}
}
- Create a new default class and trait inside of
app/services/comms/email
. Traits in this package should all extend theEmailService
. Ensure appropriate tests are included.
import database.VerificationStore
import models.{EmailResponse, Verification}
import play.api.mvc.Request
import services.comms.email.EmailService
import scala.concurrent.{ExecutionContext, Future}
class DefaultNewProvider @Inject()(val config: Configuration,
val verificationStore: VerificationStore) extends NewProvider {
override val emailSenderAddress: String = config.get[String]("email-service.message-settings.from")
override val verificationSubjectLine: String = config.get[String]("email-service.message-settings.verification-subject")
override val valueFromConfigNeededForNewProvider: String = config.get[String]("email-service.new-provider-name.whatever-required-config")
}
trait NewProvider extends EmailService {
val valueFromConfigNeededForNewProvider: String
override def sendEmailVerificationMessage(to: String, record: Verification)(implicit req: Request[_], ec: ExecutionContext): Future[EmailResponse] = {
//What ever logic is needed to send an email via the new provider
// Should return a Future EmailResponse
Future.successful(EmailResponse(
provider = "new-provider-name",
userId = record.userId,
messageId = "some email message id returned from the new email provider"
))
}
}
- Add new class to Gatekeepers Service bindings in
app/global/ServiceBindings
private def emailService(config: Configuration): Seq[Binding[_]] = {
config.get[String]("email-service.selected-provider") match {
case "ses" => Seq(bind[EmailService].to[DefaultSesService].eagerly())
case "mailgun" => Seq(bind[EmailService].to[DefaultMailgunService].eagerly())
case "new-provider-name" => Seq(bind[EmailService].to[DefaultNewProvider].eagerly())
case _ => throw new RuntimeException("Invalid email provider")
}
}
- Create a pull request
This code is open sourced licensed under the Apache 2.0 License