Giter Site home page Giter Site logo

myndocs / kotlin-oauth2-server Goto Github PK

View Code? Open in Web Editor NEW
148.0 4.0 26.0 350 KB

Flexible OAuth2 server library. Support for multiple frameworks

License: Apache License 2.0

Kotlin 100.00%
kotlin oauth2-server ktor javalin oauth2 sparkjava http4k hexagon

kotlin-oauth2-server's Introduction

Kotlin OAuth2 server

Goal

The goal of this project is to provide a simple OAuth2 library which can be implemented in any framework

Configuring the oauth2 server for any framework should be simple and understandable. It encourages to adapt to existing implementations instead the other way around.

Frameworks

Setup

Maven

<properties>
    <myndocs.oauth.version>0.7.1</myndocs.oauth.version>
</properties>

<dependencies>
    <dependency>
        <groupId>nl.myndocs</groupId>
        <artifactId>oauth2-server-core</artifactId>
        <version>${myndocs.oauth.version}</version>
    </dependency>
    
    <!-- In memory dependencies -->
    <dependency>
        <groupId>nl.myndocs</groupId>
        <artifactId>oauth2-server-client-inmemory</artifactId>
        <version>${myndocs.oauth.version}</version>
    </dependency>
    <dependency>
        <groupId>nl.myndocs</groupId>
        <artifactId>oauth2-server-identity-inmemory</artifactId>
        <version>${myndocs.oauth.version}</version>
    </dependency>
    <dependency>
        <groupId>nl.myndocs</groupId>
        <artifactId>oauth2-server-token-store-inmemory</artifactId>
        <version>${myndocs.oauth.version}</version>
    </dependency>
</dependencies>

Gradle

dependencies {
    implementation "nl.myndocs:oauth2-server-core:$myndocs_oauth_version"
    // In memory dependencies
    implementation "nl.myndocs:oauth2-server-client-inmemory:$myndocs_oauth_version"
    implementation "nl.myndocs:oauth2-server-identity-inmemory:$myndocs_oauth_version"
    implementation "nl.myndocs:oauth2-server-token-store-inmemory:$myndocs_oauth_version"
}

Framework implementation

The following frameworks are supported:

Configuration

Routing

Default endpoints are configured:

Type Relative url
token /oauth/token
authorize /oauth/authorize
token info /oauth/tokeninfo

These values can be overridden:

tokenEndpoint = "/custom/token"
authorizationEndpoint = "/custom/authorize"
tokenInfoEndpoint = "/custom/tokeninfo"

In memory

In memory implementations are provided to easily setup the project.

Identity

On the InMemoryIdentity identities can be registered. These are normally your users:

identityService = InMemoryIdentity()
    .identity {
        username = "foo-1"
        password = "bar"
    }
    .identity {
        username = "foo-2"
        password = "bar"
    }

Client

On the InMemoryClient clients can be registered:

clientService = InMemoryClient()
    .client {
        clientId = "app1-client"
        clientSecret = "testpass"
        scopes = setOf("admin")
        redirectUris = setOf("https://localhost:8080/callback")
        authorizedGrantTypes = setOf(
                AuthorizedGrantType.AUTHORIZATION_CODE,
                AuthorizedGrantType.PASSWORD,
                AuthorizedGrantType.IMPLICIT,
                AuthorizedGrantType.REFRESH_TOKEN
        )
    }
    .client {
            clientId = "app2-client"
            clientSecret = "testpass"
            scopes = setOf("user")
            redirectUris = setOf("https://localhost:8080/callback")
            authorizedGrantTypes = setOf(
                    AuthorizedGrantType.AUTHORIZATION_CODE
            )
        }

Token store

The InMemoryTokenStore stores all kinds of tokens.

tokenStore = InMemoryTokenStore()

Converters

Access token converter

By default UUIDAccessTokenConverter is used. With a default time-out of 1 hour. To override the time-out for example to half an hour:

accessTokenConverter = UUIDAccessTokenConverter(1800)

To use JWT include the following dependency:

<dependency>
    <groupId>nl.myndocs</groupId>
    <artifactId>oauth2-server-jwt</artifactId>
    <version>${myndocs.oauth.version}</version>
</dependency>

This uses auth0 jwt. To configure:

accessTokenConverter = JwtAccessTokenConverter(
        algorithm = Algorithm.HMAC256("test123"), // mandatory
        accessTokenExpireInSeconds = 1800, // optional default 3600
        jwtBuilder = DefaultJwtBuilder // optional uses DefaultJwtBuilder by default
)

Refresh token converter

By default UUIDRefreshTokenConverter is used. With a default time-out of 1 hour. To override the time-out for example to half an hour:

refreshTokenConverter = UUIDRefreshTokenConverter(1800)

To use JWT include the following dependency:

<dependency>
    <groupId>nl.myndocs</groupId>
    <artifactId>oauth2-server-jwt</artifactId>
    <version>${myndocs.oauth.version}</version>
</dependency>

This uses auth0 jwt. To configure:

refreshTokenConverter = JwtRefreshTokenConverter(
        algorithm = Algorithm.HMAC256("test123"), // mandatory
        refreshTokenExpireInSeconds = 1800, // optional default 86400
        jwtBuilder = DefaultJwtBuilder // optional uses DefaultJwtBuilder by default
)

Code token converter

By default UUIDCodeTokenConverter is used. With a default time-out of 5 minutes. To override the time-out for example 2 minutes:

codeTokenConverter = UUIDCodeTokenConverter(120)

kotlin-oauth2-server's People

Contributors

a-p-o avatar adhesivee avatar dependabot[bot] avatar pedrodbflores avatar rui-ferreira avatar serii833 avatar yektadev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

kotlin-oauth2-server's Issues

How to use?

I'm totally new, can you provide some info how to use it in my REST endpoints? I'm using this lib for Ktor

I've installed the feature but how I can access Oauth2TokenService class with /auth endpoint?

Proper interfaces for token, client and identity objects

Is your feature request related to a problem? Please describe.
A lot of database requests can be avoided if we can use our own implementations, i get 10ms overheads every time an operation is performed, and it accumulates rapidly. With proper interfaces caching could be used.

Describe the solution you'd like
Replace the data classes

nl.myndocs.oauth2.client.Client
nl.myndocs.oauth2.identity.Identity 
nl.myndocs.oauth2.token.AccessToken
nl.myndocs.oauth2.token.CodeToken
nl.myndocs.oauth2.token.RefreshToken

with interfaces
the data classes become the default implementation
token converters would need to be supplied to the config to avoid casting errors

Describe alternatives you've considered
shooting myself in the head because it's impossible to tiptoe around the issues as those classes are final.

Add id_token to TokenResponse

Is your feature request related to a problem? Please describe.
It would be nice to be able to support OpenIDConnect ID Token in the TokenResponse issued by the authorize calls.

Describe the solution you'd like
Related to #50 which would allow to add custom metadata to AT and open the Identity information, it would be nice to be able to create an ID token in the Token response to comply with OIDC specification

Describe alternatives you've considered
The TokenResponse being closed and the conversion from AT to TokenResponse hard coded I see no other way to handle that, except relying on a ThreadLocal :(

Ktor KtorCallContext respondStatus() doesn't return status to client

Describe the bug
KtorCallContext seems to be not implemented correctly.
respondStatus() only set's a status code, but never sends it to the client, which leeds to a timeout.

This is e.g. problematic in the catch block of CallRouter::routeAuthorizationCodeRedirect

        } catch (unverifiedIdentityException: InvalidIdentityException) {
            callContext.respondStatus(STATUS_UNAUTHORIZED)

            return RedirectRouterResponse(false)
        }

Headers are case sensetive despite RFC 2616

Describe the bug
In particular, I noticed this with the "Authorization" header. When authorizing Identities, the authorization must be lower case because of the implementation of BasicAuthorizer#extractCredentials. RFC 2616 states

Field names are case-insensitive

To Reproduce

  1. Create ktor project with the default setup in the README.md
  2. Try to authenticate with curl -X GET -H 'authorization: Basic Zm9vOmJhcg==' -i 'http://localhost:8080/oauth/authorize?response_type=code&client_id=testapp&redirect_uri=https://localhost:8080/callback'. The request should work as expected.
  3. Now, change the case of the header to curl -X GET -H 'Authorization: Basic Zm9vOmJhcg==' -i 'http://localhost:8080/oauth/authorize?response_type=code&client_id=testapp&redirect_uri=https://localhost:8080/callback'. This request will fail with a 401 because of the BasicAuthorizer class.

Expected behavior
The request should succeed with a 302 as if it was lowercase.

Additional context
All headers should be case insensitive, and they are usually capitalized as a standard.

UserInfo should be TokenInfo

During the implementation of #30 it was decided that the user info endpoint should become a token info endpoint.

Questions:

  1. Is it intended that this be the endpoint described here
  2. How will auth be handled for this endpoint? Should it require a bearer token with a token_info scope?
  1. How many of the optional response fields should be supported? I think all.

How to encapsulate requests into the "authenticated" part in ktor?

Let me start with an issue.

In ktor, when you want to add one auth system (basic, for example) yo can do something like this:

install(Authentication) {
        basic(AUTH) {
            realm = REALM

            validate { credentials ->
                if (credentials.name == AUTH_USER && credentials.password == AUTH_PASSWORD) {
                    UserIdPrincipal(credentials.name)
                } else {
                    null
                }
            }
        }
    }

And then, to specify which requests need auth, we do that:

routing {
        authenticate(AUTH) {
            route("/api") {
                post("/test") { call.respond("Hello from authenticated part!") }
            }
        }
    }

How can we specify this behaviour with this lib?

Add a gradle configuration guide

In the Java/Kotlin world, some people use Gradle instead of maven.

It would be pretty nice to have a small guide on how to use kotlin-oauth2-server with gradle.

Ability to add metadata to access and refresh tokens

Is your feature request related to a problem? Please describe.
I can't pass any metadata along with the access token, i.e. to the token store. Also there's some fields missing that could be useful if one is using JWTs as ATs - such as the jti (token id) and aud (audience).

Describe the solution you'd like
A way to pass metadata, i.e. a String -> Any map on the AT class. Also possibly add an optional id field to the AT, for the use case where your access token isn't an id itself.

Describe alternatives you've considered

  • Make the Access Token class open so it can be extended
  • Let the access token be an interface rather than a data class

Additional context
Maybe the same for refresh tokens. Possibly also for TokenInfo so metadata can be shown in the token info endpoint? (unsure whether that's desired or not but it sure would be handy)

Form login authorize endpoint

Last changes allow to create form login on authorization endpoint.
It might be unclear how to do it. This could be added to documentation.

JWT Support

Is your feature request related to a problem? Please describe.
Add JWT feature for AccessToken. It will be great for a case when I have an auth server where I validate user and data server, where I would like to get content by userId (which can be stored in JWT payload) and expireAt (from JWT's "iat").

Describe the solution you'd like
There will be an option to switch between UUID AccessToken and JWT AccessToken. All fields of AccessToken like "username", "clientId" can be stored inside JWT payload.

Describe alternatives you've considered
The only opportunity I've found to do it is to override AccessTokenConverter, and for field "accessToken" generate a JWT string.

Allow extension of grant types

Oauth2 supports extending a server with custom grant types, as described i.e. here:

OAuth 2.0 also supports extension grant types allowing organizations to define their own custom grant types to support additional client types or to provide a bridge between OAuth and existing systems.
https://www.oauth.com/oauth2-servers/differences-between-oauth-1-2/user-experience-alternative-token-issuance-options/)

Problem:
Allowed grant types seem to be hard-coded i.e. in the CallRouter as of now.

Solution
There should be away of configuring your own custom grant types and their corresponding flows.

Alternatives
N/A

Other info
(Have taken this lib for a spin now, looks really awesome so far!)

Bintray is deprecated

Is your feature request related to a problem? Please describe.
There is no way to import this lib by gradle/maven because of bintray is deprecated and downloader of dependencies doesn't work.

Describe the solution you'd like
A good solution would be update readme, and describe a HOWTO's list to generate and include the .jars from the .zip file. So people can use and download this lib without of an external-dependencies-server.

Describe alternatives you've considered

  • Update HowTo's to don't depend of external business
  • Bintray alternatives

Additional context
TY for your work!
Best regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.