Keycloak how to get data in protocol mapper from custom authenticator? - java

I have created on CustomAuthenticator as below:
public class MyCustomAuthenticator extends UsernamePasswordForm {
#Override
public boolean validatePassword(final AuthenticationFlowContext context, final UserModel user,
final MultivaluedMap<String, String> inputData, final boolean clearUser) {
context.getSession().setAttribute("data","test");
}
}
but when i tried to get it on protocol mapper as below:
public class RmDataTokenMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
#Override
protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession, KeycloakSession keycloakSession, ClientSessionContext clientSessionCtx) {
keycloakSession.sessions().getKeycloakSession().getAttribute("data");
}
}
I am not able to get data. Any one help me how to achieve?

Related

How to access custom bpmn extension elements with camunda java api?

I have a Bpmn file with an extension element like this.
<bpmn:extensionElements>
<zeebe:taskDefinition type="customer-interaction-service" retries="0" />
<zeebe:taskHeaders>
<zeebe:header key="operation" value="save" />
<zeebe:header key="#type" value="Organization[]" />
<zeebe:header key="updateReliesOnReferredTypes" value="#Customer.engagedParty" />
</zeebe:taskHeaders>
</bpmn:extensionElements>
I want to access the header elements and get keys and values.
I followed this tutorial for cmn but Bpmn api did not register my custom classes.
You can clone full code from here
I copppy some important parts here.
Main class:
public class Main {
public static void main(String[] args) {
InputStream is = Main.class.getResourceAsStream("/dclm-addservice.bpmn");
BpmnModelInstance model =CustomBpmn.readModelFromStream(is );
ServiceTask serviceTask=model.getModelElementById("ServiceTask_1jn441o");
int count=serviceTask.getExtensionElements().getElementsQuery().filterByType(TaskHeaders.class).count();
System.out.println(count);
count=serviceTask.getExtensionElements().getElementsQuery().count();
System.out.println(count);
}
}
result:
0
2
When filtering by TaskHeaders.class, it has 0 result.
customBpmn
public class CustomBpmn extends Bpmn {
public static CustomBpmn INSTANCE = new CustomBpmn();
public CustomBpmn() {
super();
System.out.println("constructor");
}
#Override
protected void doRegisterTypes(ModelBuilder modelBuilder) {
super.doRegisterTypes(modelBuilder);
System.out.println("registering");
HeaderImpl.registerType(modelBuilder);
TaskHeadersImpl.registerType(modelBuilder);
}
}
header interface
public interface Header extends BpmnModelElementInstance {
public String getKey();
public void setKey(String key);
public String getValue();
public void setValue(String value);
}
TaskHeaders interface
public interface TaskHeaders extends BpmnModelElementInstance {
Collection<Header> getHeaders();
void addHeader(Header header);
boolean addHeaders(List<Header> headers);
List<Header> findByKey(String key);
}
HeaderImpl
public class HeaderImpl extends BpmnModelElementInstanceImpl implements Header {
protected static Attribute<String> keyAttribute;
protected static Attribute<String> valueAttribute;
public static void registerType(ModelBuilder modelBuilder) {
ModelElementTypeBuilder typeBuilder = modelBuilder.defineType(Header.class, HEADER)
.namespaceUri(ZEEBE_SCHEMA)
.instanceProvider(new ModelTypeInstanceProvider<Header>() {
public Header newInstance(ModelTypeInstanceContext instanceContext) {
return new HeaderImpl(instanceContext);
}
});
keyAttribute =typeBuilder.stringAttribute(KEY_NAME)
.namespace(ZEEBE_SCHEMA)
.build();
valueAttribute =typeBuilder.stringAttribute(VALUE_NAME)
.namespace(ZEEBE_SCHEMA)
.build();
typeBuilder.build();
}
public HeaderImpl(ModelTypeInstanceContext instanceContext) {
super(instanceContext);
}
//some getter and setters.
TaskHeadersImple
public class TaskHeadersImpl extends BpmnModelElementInstanceImpl implements TaskHeaders {
protected static ChildElementCollection<Header> headerCollection;
public static void registerType(ModelBuilder modelBuilder) {
ModelElementTypeBuilder typeBuilder = modelBuilder.defineType(TaskHeaders.class, TASK_HEADERS)
.namespaceUri(ZEEBE_SCHEMA)
.instanceProvider(new ModelTypeInstanceProvider<TaskHeaders>() {
public TaskHeaders newInstance(ModelTypeInstanceContext instanceContext) {
return new TaskHeadersImpl(instanceContext);
}
});
SequenceBuilder sequenceBuilder = typeBuilder.sequence();
headerCollection =sequenceBuilder.elementCollection(Header.class)
.build();
typeBuilder.build();
}
public TaskHeadersImpl(ModelTypeInstanceContext instanceContext) {
super(instanceContext);
}
//some getters and setters.
Thanks.
Edit:
I could access TaskHeaders by using Zeebe java api instead of Camunda java api but the above question is still valid because TaskHeaders are not custom bpmn elements for zeebe modeler java api but are custom extension for Camunda.

#RequestHeader not binding in POJO but binding only in variable

I am not able to bind the request header values into a POJO class. Here is an explanation:
I want to bind the value of "isKidsProfile" into "DetailCO" but it is not binding. On the other hand, it is working if I am binding it into a variable only.
// consider header value in request is: key:isKidsProfile and value:true/false
#RequestMapping(value = "/api/v1/detail/{id}", method = RequestMethod.GET)
public ResponseDTO fetchDetailForKidsProfileUser(
#RequestHeader DetailCO detailCO,
#RequestHeader boolean isKidsProfile) {
sout(detailCO.isKidsProfile); // not bind in object
sout(isKidsProfile); // bind in variable
return new ResponseDTO();
}
class DetailCO {
private boolean isKidsProfile;
//getters ans setters
}
There are more values so it will be good to bind in POJO rather than creating multiple variables. Please suggest.
This is what I have used for my use case where I needed to parse all Parameters. You may use RequestHeaderMethodArgumentResolver if it's just the headers.
Create a configuration
#Configuration
public class IRSConfig implements WebMvcConfigurer {
#Autowired
private IRSArgumentResolver irsArgumentResolver;
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(irsArgumentResolver);
}
}
Create POJO class for encapsulating your data and sending to RequestHandler
public class MyRequestParams {
private String first;
private String second;
public void setFirst(String first) {
this.first = first;
}
public void setSecond(String second) {
this.second = second;
}
public String getFirst() {
return first;
}
public String getSecond() {
return second;
}
}
Create an argument resolver
#Component
public final class IRSArgumentResolver implements HandlerMethodArgumentResolver {
#Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.getParameterType().equals(MyRequestParams.class);
}
#Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
MyRequestParams requestParams = new MyRequestParams();
requestParams.setFirst(nativeWebRequest.getParameter("x-et-participant-id"));
requestParams.setSecond(nativeWebRequest.getHeader("Authorization"));
return requestParams;
}
}
You should be able to register a Converter<String, DeailCO>.

What's a good way to store class properties and load at run time?

I have a messaging producer (RabbitMQ) and depending on what kind of message i have to send, i need to change the routing key and exchange at runtime.
Given this i'd implemented a strategy to load each class with specific properties, but it's not appear a good solution.
For example:
public class MyProducerStrategy1 extends RabbitMessagingProducer {
private static final String ROUTING_KEY = "order1";
private static final String EXCHANGE = "myexchange1";
#Override
String getRoutingKey() {
return ROUTING_KEY;
}
#Override
String getExchange() {
return EXCHANGE;
}
#Override
public void sendMessage(Message message) {
super.sendMessage(message);
}
}
public class MyProducerStrategy2 extends RabbitMessagingProducer {
private static final String ROUTING_KEY = "fullfilment";
private static final String EXCHANGE = "myexchange2";
#Override
String getRoutingKey() {
return ROUTING_KEY;
}
#Override
String getExchange() {
return EXCHANGE;
}
#Override
public void sendMessage(Message message) {
super.sendMessage(message);
}
}
public abstract class RabbitMessagingProducer implements MessagingProducerStrategy {
#Autowired
private RabbitTemplate rabbitTemplate;
abstract String getRoutingKey();
abstract String getExchange();
#Override
public void sendMessage(Message message) {
rabbitTemplate.convertAndSend(getExchange(), getRoutingKey(), message);
}
}
Does it make sense? or there's another approach to load there properties and have maybe one class?
Do not create multiple class for this scenario.
load the files from a property file based on the message.
Another option is to create a static map of values with message types as the key and routing key as the value. Fetch the values from the map based on the message type.

How to provide your services via #Context in Neo4j unmanaged extension

I have Neo4j unmanaged extension. I want some services to be created as singletons and be available via #Context in my resources.
Something like this:
#Path("/example")
public class ExampleResource {
public ExampleResource(#Context CostlyService costlyService) { // <<---
// use it here
}
}
How this can be achieved?
Neo4j has PluginLifecycle interface that give us possibility to hook into Neo4j server lifecycle and provide our own services for injection blog post.
So, we have service. Let's take this one as example:
public interface CostlyService {
}
public class CostlyServiceImpl implements CostlyService {
public CostlyService() {
// a LOT of work done here
}
//...
}
Now we need to make our own PluginLifecycle implementation:
public class ExamplePluginLifecycle implements PluginLifecycle {
#Override
public Collection<Injectable<?>> start(GraphDatabaseService graphDatabaseService,
Configuration config) {
final List<Injectable<?>> injectables = new ArrayList<>();
return injectables;
}
#Override
public void stop() {
}
}
As you see, injectable list is empty for now. We will add our service there soon.
Important: you must register your PluginLifecycle implementation, so it will be available via SPI:
// file: META-INF/services/org.neo4j.server.plugins.PluginLifecycle
my.company.extension.ExamplePluginLifecycle
This will make your PluginLifecycle discoverable by Neo4j server.
Now we need to create actual injectable. Let's write implementation for Injectable interface:
public final class TypedInjectable<T> implements Injectable<T> {
private final T value;
private final Class<T> type;
private TypedInjectable(final T value, final Class<T> type) {
this.value = value;
this.type = type;
}
public static <T> TypedInjectable<T> injectable(final T value, final Class<T> type) {
return new TypedInjectable<>(value, type);
}
#Override
public T getValue() {
return value;
}
#Override
public Class<T> getType() {
return type;
}
}
This will serve as simple container for our service. Usage:
import static my.company.extension.TypedInjectable.injectable;
injectable(new CostlyServiceImpl(), CostlyService.class);
Now we can add our injectable into PluginLifecycle.
#Override
public Collection<Injectable<?>> start(GraphDatabaseService graphDatabaseService,
Configuration config) {
final List<Injectable<?>> injectables = new ArrayList<>();
injectables.add(injectable(new CostlyServiceImpl, CostlyService.class)); // <<---
return injectables;
}
After this change our CostlyService will be available for our resources via #Context:
#Path("/example")
public class ExampleResource {
public ExampleResource(#Context CostlyService costlyService) {
// use it here
}
// ...
}
Tip: keep your PluginLifecycle's in same package or in subpackage with your resources.

Injecting principal into resource method in Jersey 2

I am developing a REST API using Jersey 2 and at the moment I am trying to incorporate basic authentication by use of an annotation similar to the #Auth found in Dropwizard. With
#Path("hello")
public class HelloResource {
#GET
#Produces("application/json")
public String hello(#Auth final Principal principal) {
return principal.getUsername();
}
}
the hello resource invocation should be intercepted by some code performing basic authentication using the credentials passed in the Authorization HTTP request header and on success injecting the principal into the method principal parameter.
I have started creating an #Auth resolver, see below, but I do not see how I can access the Authorization HTTP request header from within that?
#Singleton
public class AuthResolver {
public static class AuthInjectionResolver extends ParamInjectionResolver<Auth> {
public AuthInjectionResolver() {
super(AuthValueFactoryProvider.class);
}
}
#Singleton
public static class AuthValueFactoryProvider extends AbstractValueFactoryProvider {
#Inject
public AuthValueFactoryProvider(final MultivaluedParameterExtractorProvider extractorProvider, final ServiceLocator injector) {
super(extractorProvider, injector, UNKNOWN);
}
#Override
protected Factory<?> createValueFactory(final Parameter parameter) {
final Class<?> classType = parameter.getRawType();
return classType == null || !classType.equals(Principal.class) ? null :
new AbstractContainerRequestValueFactory<Principal>() {
#Override
public Principal provide() {
// Authentication?
}
};
}
}
public static class Binder extends AbstractBinder {
#Override
protected void configure() {
bind(AuthValueFactoryProvider.class).to(ValueFactoryProvider.class).in(Singleton.class);
bind(AuthInjectionResolver.class).to(
new TypeLiteral<InjectionResolver<Auth>>() {
}
).in(Singleton.class);
}
}
}
How to approach this? :)
Ah, in AbstractContainerRequestValueFactory<Principal> I can add
#Context private ResourceContext context;
and then extract the HTTP request and it's headers from there inside the provide method.

Categories