oauthly
OAuth 2.0 Compliant Authorization and Resource Server in Java with Play Framework. Suitable for being the Authorization Server for your software platform, with SSO and social provider login support.
There are a lot of authorization server examples on many platforms, such as Spring Boot, Play Framework, etc, but none works as a full-fledged authorization server. This one does, for free. The functionality is comparable to auth0, will be better in the future (with your PRs, of course).
This project was started as a Spring Boot project (on branch spring-boot
) then I have recently fully converted it to Play Framework. The reason for this change is the superior features of Play Framework, and a little bit of curiousity on my side.
Features
- Uses Play Framework (Java) 2.6.x
- Fully supported OAuth2 grant types: client credentials, authorization code, resource owner password, refresh token
- Login, register, profile, user management, client management and authorize client views with Bootstrap
- Supports logging in with social providers and advanced account linking features
- Supports sending email confirmation links
- Utilizes JWT for tokens, authorization codes and cookies
- Completely stateless server side logic
- Logged-in users are remembered with long-term safe cookies
- Multiple client id and secret pairs are supported, managed by a view
- Customizable expiry times for generated tokens (see
application.conf
file) - Google reCAPTCHA support on endpoints (with
@RecaptchaProtected
annotation) - OAuth2 scopes support
- MongoDB backend
- Mailgun API integration for sending emails
- Uses bcrypt for user passwords, twirl for templating
- Discourse SSO support, see this
Instructions for local mode
- Have a running mongodb instance and
sbt
installed. sbt run
- Go to http://localhost:9000, register a new account for yourself. All accounts are required to confirm email addresses. To receive emails, you need to get your own mailbox api key. For demo purposes, the confirmation link is logged on console after you register. Copy and paste the link on your browser to finalize account creation. First account will be given admin access.
- You can also enable login with Facebook, Google or any other OAuth 2.0 Authorization Server.
- For Facebook, go to https://developers.facebook.com/apps/ and create yourself an app with redirect uri
http://localhost:9000/oauth/client/facebook/callback
, then put its client id and secret toapplication.conf
. You may need some additional settings on your Facebook app. Consult their documentation. - For Google, go to https://console.developers.google.com/apis/credentials and create an OAuth Client ID with redirect url
http://localhost:9000/oauth/client/google/callback
, then put its client id and secret toapplication.conf
. You will also need to enable Google People API. Consult their documentation. - For any other OAuth 2.0 Authorization Server, see this
- For Facebook, go to https://developers.facebook.com/apps/ and create yourself an app with redirect uri
- By now, you have authenticated yourself as an admin on OAuthly platform. Now you will configure your applications and services (OAuth 2.0 Clients) to connect to OAuthly (OAuth 2.0 Authorization Server). Go to http://localhost:9000/client to create one client, by setting its
name
andredirect_uri
. - Set generated Client ID and Client Secret and following endpoint addresses on your OAuth 2.0 Client Application:
-
Authorize endpoint: http://localhost:9000/oauth/authorize
Example:
curl -v 'http://localhost:9000/oauth/authorize?client_id=vpNS2x3QTVSxjTuWUrY3&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Flogin'
-
Token endpoint: http://localhost:9000/oauth/token (Use POST with FORM parameters)
Example:
curl -v -X POST -d 'grant_type=authorization_code&code=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoIjoxMDI1MDQ5NzEzLCJyIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2xvZ2luIiwiZXhwIjoxNTE1MDg0OTM3LCJ2dCI6MywiZyI6IjExbU9tMHVVMEQwOHMxSXo5S3RMIn0.wtLx54iK1kEWhXAVU5gb6AnyPQnN1Qb2r4L-s20TADk&client_id=vpNS2x3QTVSxjTuWUrY3&client_secret=0JPSlNiGKRmcgqidu77s&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Flogin' 'http://localhost:9000/oauth/token'
-
User info endpoint: http://localhost:9000/api/me (Use
Authorization: Bearer token
header)Example:
curl -v -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoIjoxMDI1MDQ5NzEzLCJleHAiOjE1MTUwODUxNTYsImdyYW50IjoiMTFtT20wdVUwRDA4czFJejlLdEwiLCJ2dCI6MX0.sl4F-ik9Tstw38JxOSfHYUCi1cN4NxYmqgNCoA0hIbA" http://localhost:9000/api/me
Instructions for production mode
Please first follow the instructions for local mode AND run it on your local machine before attempting this. If you don't have that much time, AT LEAST read them once.
- OAuthly must run on a seperate domain. If your domain is
example.com
, running onoauthly.example.com
is recommended. sbt stage
in root folder to prepare distribution.- Move
target/universal/stage/oauthly-1.0-SNAPSHOT.zip
to your server and extract it to some place. - Set your smtp configurations for
play.mailer
and setmock=false
or create account on http://mailgun.com and get a (free) API key for a valid domain of yours. - Create account on https://www.google.com/recaptcha/admin and get
recaptcha.siteKey
andrecaptcha.secret
. - (Optional) If you want to allow Login with Facebook and/or Google, get your keys as specified above.
- Prepare
conf/prod.conf
file from following template. Put random values forjwt.secret
andplay.http.secret.key
.
include "application.conf"
http.port=9000
play.filters.enabled=[
play.filters.csrf.CSRFFilter,
play.filters.headers.SecurityHeadersFilter,
play.filters.hosts.AllowedHostsFilter,
]
play.filters.hosts.allowed = ["oauthly.example.com"]
playjongo.uri="mongodb://127.0.0.1:27017/oauthly"
play.http.secret.key=
jwt.secret=
recaptcha.enabled=true
recaptcha.siteKey=
recaptcha.secret=
use.secure.session.cookie=true
mail.mailgun.key=key-123
mail.mailgun.domain=example.com
mail.mailgun.from="OAuthly <noreply@example.com>"
brand.name="My Brand"
tos.text="""
Terms of Service content
"""
oauth.providers=[
{
key=facebook
displayName=Facebook
clientId=
clientSecret=
tokenUrl="https://graph.facebook.com/v2.11/oauth/access_token"
authorizeUrl="https://www.facebook.com/v2.11/dialog/oauth"
scopes="public_profile email"
userInfoUrl="https://graph.facebook.com/me?fields=id,name,email"
}
]
bin/oauthly -Dconfig.resource=prod.conf
to start the server.- TLS is a must! You can follow https://www.playframework.com/documentation/2.6.x/ConfiguringHttps for configuring it but I recommend setting up TLS on a reverse proxy like nginx.
Custom OAuth2 Provider
Currently we implement Facebook and Google OAuth2 clients. Every vendor may implement the token and user info retrieval part differently. Follow below steps for a new OAuth2 client implementation.
- Put relevant config block in
application.conf
. - Set
tokenRetriever
andcurrentUserIdentifier
inAuthorizationServerManager
class. Onlyid
is necessary for identifying users in remote system. If you map email addresses in remote system to OAuthly, the confirmation step will be bypassed resulting in a smoother sign-up process. - We use bootstrap-social for provider login buttons, fork it if necessary.
Discourse SSO
OAuthly fully supports Discourse SSO integration. In this configuration, the single source of users becomes oauthly. When Login button is clicked on Discourse, user is redirected to oauthly login page. If the user has already authenticated with oauthly with a long term token, he/she immediately gets redirected back to discourse with user information. Follow the instructions below to configure your system.
- Login with admin and go to /discourse
- Tick enabled in discourse settings panel, enter sso return url. It is usually
http://DISCOURSE_SERVER/session/sso_login
- Hit save and copy the generated secret
- Open discourse Admin -> Settings -> Login,
- 'enable sso' -> true
- 'sso url' ->
http://OAUTHLY_SERVER/discourse/sso
- 'sso secret' -> (secret from step 3)
- 'sso overrides username and email' -> true
- Users -> 'logout redirect' ->
http://OAUTHLY_SERVER/logout
- Done, you may test the integration. Remember that the admin account must have the same email address on both systems, or you'll get locked out.
Screenshots (needs update)
TODO (PRs are welcome!)
- Enable/disable user account function on user management view
- Possible production example with let's encrypt certificates, docker container and nginx
- Scope CRUD screen
- Permissions model
- More social provider support (github, etc)