Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api-gateway/security/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version=2.0.0-SNAPSHOT
knotx.version=2.0.0
version=2.1.1-SNAPSHOT
knotx.version=2.1.1-SNAPSHOT
knotx.conf=knotx
docker.image.name=knotx-example/secure-api-gateway
19 changes: 19 additions & 0 deletions api-gateway/security/knotx/conf/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ paths:
description: Hello World API protected with JWT
'401':
description: Unauthorized access
/api/secure/oauth2:
get:
operationId: hello-world-operation-oauth2
security:
- helloOAuth2Auth: []
responses:
'200':
description: Hello World API protected with OAuth2
'401':
description: Unauthorized access

components:
securitySchemes:
Expand All @@ -63,3 +73,12 @@ components:
type: http
scheme: bearer
bearerFormat: JWT
helloOAuth2Auth:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://accounts.google.com/o/oauth2/v2/auth
tokenUrl: https://accounts.google.com/o/oauth2/v4/token
scopes:
https://www.googleapis.com/auth/userinfo.profile: read user info

23 changes: 23 additions & 0 deletions api-gateway/security/knotx/conf/routes/operations.conf
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,32 @@ routingOperations = ${routingOperations} [
}
]
}
{
operationId = hello-world-operation-oauth2
handlers = [
{
name = helloOpenIdHandler
config = {
message = "Hello World From Knot.x with OAuth2!"
}
}
]
}
]

securityHandlers = [
{
schema = helloOAuth2Auth
factory = helloOAuth2AuthFactory
config = {
clientId = ${googleConfig.clientId}
clientSecret = ${googleConfig.clientSecret}
redirectUrl = "http://localhost:8092/api/secure/callback"
scopes = [
"https://www.googleapis.com/auth/userinfo.profile"
]
}
}
{
schema = helloBasicAuth
factory = helloBasicAuthFactory
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.knotx.example.hellohandler;

import io.knotx.server.api.handler.RoutingHandlerFactory;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.reactivex.core.Vertx;
import io.vertx.reactivex.ext.auth.oauth2.KeycloakHelper;
import io.vertx.reactivex.ext.web.RoutingContext;

public class HelloWorldOpenIDHandlerFactory implements RoutingHandlerFactory {

@Override
public String getName() {
return "helloOpenIdHandler";
}

@Override
public Handler<RoutingContext> create(Vertx vertx, JsonObject config) {
return event -> {
String name = KeycloakHelper.idToken(event.user().principal())
.getString("name");
event.response().end("Hello " + name);
};
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
io.knotx.example.hellohandler.HelloWorldHandlerFactory
io.knotx.example.hellohandler.HelloWorldHandlerFactory
io.knotx.example.hellohandler.HelloWorldOpenIDHandlerFactory
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package io.knotx.examples.security.auth;

import io.knotx.server.api.security.AuthHandlerFactory;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.oauth2.OAuth2ClientOptions;
import io.vertx.ext.auth.oauth2.OAuth2FlowType;
import io.vertx.reactivex.core.Vertx;
import io.vertx.reactivex.ext.auth.oauth2.OAuth2Auth;
import io.vertx.reactivex.ext.web.Router;
import io.vertx.reactivex.ext.web.handler.AuthHandler;
import io.vertx.reactivex.ext.web.handler.OAuth2AuthHandler;

public class OAuth2HelloHandlerFactory implements AuthHandlerFactory {

private OAuth2AuthHandler oAuth2AuthHandler;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if configuration contains two entries for this OAuthHelloHandlerFactory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in io.knotx.server.SecurityProvider reference to factories is a map<factoryName, factory reference>, so it will be unique anyway


@Override
public String getName() {
return "helloOAuth2AuthFactory";
}

@Override
public AuthHandler create(Vertx vertx, JsonObject config) {
OAuth2ClientOptions clientOptions = new OAuth2ClientOptions()
.setClientID(config.getString("clientId"))
.setClientSecret(config.getString("clientSecret"))
.setSite("https://accounts.google.com")
.setTokenPath("https://www.googleapis.com/oauth2/v4/token")
.setAuthorizationPath("/o/oauth2/auth")
.setUserInfoPath("https://www.googleapis.com/oauth2/v3/userinfo")
.setIntrospectionPath("https://www.googleapis.com/oauth2/v3/tokeninfo")
.setUserInfoParameters(new JsonObject().put("alt", "json"))
.setScopeSeparator(" ")
.setUseBasicAuthorizationHeader(false);

OAuth2Auth authProvider = OAuth2Auth.create(vertx, OAuth2FlowType.AUTH_CODE, clientOptions);

oAuth2AuthHandler = OAuth2AuthHandler.create(authProvider, config.getString("redirectUrl"));
config.getJsonArray("scopes").forEach(scope -> oAuth2AuthHandler.addAuthority((String) scope));

return oAuth2AuthHandler;
}

@Override
public void registerCustomRoute(Router router) {
oAuth2AuthHandler.setupCallback(router.route());
}
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
io.knotx.examples.security.auth.BasicAuthHandlerFactory
io.knotx.examples.security.auth.JwtAuthHandlerFactory
io.knotx.examples.security.auth.OAuth2HelloHandlerFactory