Search in sources :

Example 1 with Authorized

use of io.helidon.security.annotations.Authorized in project helidon by oracle.

the class AbacExplicitResource method process.

/**
 * A resource method to demonstrate explicit authorization.
 *
 * @param context  security context (injected)
 * @return "fine, sir" string; or a description of authorization failure
 */
@GET
@Authorized(explicit = true)
@AtnProvider.Authentication(value = "user", roles = { "user_role" }, scopes = { "calendar_read", "calendar_edit" })
@AtnProvider.Authentication(value = "service", type = SubjectType.SERVICE, roles = { "service_role" }, scopes = { "calendar_read", "calendar_edit" })
public Response process(@Context SecurityContext context) {
    SomeResource res = new SomeResource("user");
    AuthorizationResponse atzResponse = context.authorize(res);
    if (atzResponse.isPermitted()) {
        // do the update
        return Response.ok().entity("fine, sir").build();
    } else {
        return Response.status(Response.Status.FORBIDDEN).entity(atzResponse.description().orElse("Access not granted")).build();
    }
}
Also used : AuthorizationResponse(io.helidon.security.AuthorizationResponse) Authorized(io.helidon.security.annotations.Authorized) GET(jakarta.ws.rs.GET)

Example 2 with Authorized

use of io.helidon.security.annotations.Authorized in project helidon by oracle.

the class SecurityFilter method getMethodSecurity.

private SecurityDefinition getMethodSecurity(InvokedResource invokedResource, Method definitionMethod, ExtendedUriInfo uriInfo) {
    // Check cache
    // Jersey model 'definition method' is the method that contains JAX-RS/Jersey annotations. JAX-RS does not support
    // merging annotations from a parent, so we don't have to look for annotations on corresponding methods of interfaces
    // and abstract classes implemented by the definition method.
    // Jersey model does not have a 'definition class', so we have to find it from a handler class
    Class<?> obtainedClass = invokedResource.definitionClass().orElseThrow(() -> new SecurityException("Got definition method, cannot get definition class"));
    Class<?> definitionClass = getRealClass(obtainedClass);
    // Get the application for this request in case there's more than one
    Application appInstance = serverRequest.context().get(Application.class).get();
    // Create and cache security definition for application
    Class<?> appRealClass = getRealClass(appInstance.getClass());
    SecurityDefinition appClassSecurity = appClassSecurity(appRealClass);
    if (definitionClass.getAnnotation(Path.class) == null) {
        // this is a sub-resource
        // I must locate the resource class and method that was invoked
        PathVisitor visitor = new PathVisitor();
        visitor.visit(uriInfo.getMatchedRuntimeResources());
        Collections.reverse(visitor.list);
        StringBuilder fullPathBuilder = new StringBuilder();
        List<Method> methodsToProcess = new LinkedList<>();
        for (Invocable m : visitor.list) {
            // first the top most class (MpMainResource.sub())
            // then the one under it (MpSubResource.sub())
            // these methods are above our sub resource
            Method parentDefMethod = m.getDefinitionMethod();
            Class<?> parentClass = parentDefMethod.getDeclaringClass();
            fullPathBuilder.append("/").append(parentClass.getName()).append(".").append(parentDefMethod.getName());
            methodsToProcess.add(parentDefMethod);
        }
        fullPathBuilder.append("/").append(definitionClass.getName()).append(".").append(definitionMethod.getName());
        methodsToProcess.add(definitionMethod);
        String fullPath = fullPathBuilder.toString();
        // now full path can be used as a cache
        if (subResourceMethodSecurity(appRealClass).containsKey(fullPath)) {
            return subResourceMethodSecurity(appRealClass).get(fullPath);
        }
        // now process each definition method and class
        SecurityDefinition current = appClassSecurity;
        for (Method method : methodsToProcess) {
            Class<?> clazz = method.getDeclaringClass();
            current = securityForClass(clazz, current);
            Authenticated atn = method.getAnnotation(Authenticated.class);
            Authorized atz = method.getAnnotation(Authorized.class);
            Audited audited = method.getAnnotation(Audited.class);
            SecurityDefinition methodDef = current.copyMe();
            methodDef.add(atn);
            methodDef.add(atz);
            methodDef.add(audited);
            SecurityLevel currentSecurityLevel = methodDef.getSecurityLevels().get(methodDef.getSecurityLevels().size() - 1);
            Map<Class<? extends Annotation>, List<Annotation>> methodAnnotations = new HashMap<>();
            addCustomAnnotations(methodAnnotations, method);
            SecurityLevel newSecurityLevel = SecurityLevel.create(currentSecurityLevel).withMethodName(method.getName()).withMethodAnnotations(methodAnnotations).build();
            methodDef.getSecurityLevels().set(methodDef.getSecurityLevels().size() - 1, newSecurityLevel);
            for (AnnotationAnalyzer analyzer : analyzers) {
                AnnotationAnalyzer.AnalyzerResponse analyzerResponse = analyzer.analyze(method, current.analyzerResponse(analyzer));
                methodDef.analyzerResponse(analyzer, analyzerResponse);
            }
            current = methodDef;
        }
        subResourceMethodSecurity(appRealClass).put(fullPath, current);
        return current;
    }
    if (resourceMethodSecurity(appRealClass).containsKey(definitionMethod)) {
        return resourceMethodSecurity(appRealClass).get(definitionMethod);
    }
    SecurityDefinition resClassSecurity = resourceClassSecurity(appRealClass).computeIfAbsent(definitionClass, aClass -> securityForClass(definitionClass, appClassSecurity));
    Authenticated atn = definitionMethod.getAnnotation(Authenticated.class);
    Authorized atz = definitionMethod.getAnnotation(Authorized.class);
    Audited audited = definitionMethod.getAnnotation(Audited.class);
    SecurityDefinition methodDef = resClassSecurity.copyMe();
    methodDef.add(atn);
    methodDef.add(atz);
    methodDef.add(audited);
    int index = methodDef.getSecurityLevels().size() - 1;
    SecurityLevel currentSecurityLevel = methodDef.getSecurityLevels().get(index);
    Map<Class<? extends Annotation>, List<Annotation>> methodLevelAnnots = new HashMap<>();
    addCustomAnnotations(methodLevelAnnots, definitionMethod);
    methodDef.getSecurityLevels().set(index, SecurityLevel.create(currentSecurityLevel).withMethodName(definitionMethod.getName()).withMethodAnnotations(methodLevelAnnots).build());
    resourceMethodSecurity(appRealClass).put(definitionMethod, methodDef);
    for (AnnotationAnalyzer analyzer : analyzers) {
        AnnotationAnalyzer.AnalyzerResponse analyzerResponse = analyzer.analyze(definitionMethod, resClassSecurity.analyzerResponse(analyzer));
        methodDef.analyzerResponse(analyzer, analyzerResponse);
    }
    return methodDef;
}
Also used : Path(jakarta.ws.rs.Path) Authenticated(io.helidon.security.annotations.Authenticated) Authorized(io.helidon.security.annotations.Authorized) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) AnnotationAnalyzer(io.helidon.security.providers.common.spi.AnnotationAnalyzer) ResourceMethod(org.glassfish.jersey.server.model.ResourceMethod) Method(java.lang.reflect.Method) LinkedList(java.util.LinkedList) Annotation(java.lang.annotation.Annotation) Invocable(org.glassfish.jersey.server.model.Invocable) Audited(io.helidon.security.annotations.Audited) SecurityLevel(io.helidon.security.SecurityLevel) LinkedList(java.util.LinkedList) List(java.util.List) Application(jakarta.ws.rs.core.Application)

Example 3 with Authorized

use of io.helidon.security.annotations.Authorized in project helidon by oracle.

the class SecurityFilter method securityForClass.

/**
 * Creates security definition based on the annotations on a class and using a
 * parent as a starting point. Obtains real class before processing to skip
 * proxies.
 *
 * @param theClass class from which to create security definition
 * @param parent base security definition or {@code null}
 * @return security definition for the class
 */
private SecurityDefinition securityForClass(Class<?> theClass, SecurityDefinition parent) {
    Class<?> realClass = getRealClass(theClass);
    Authenticated atn = realClass.getAnnotation(Authenticated.class);
    Authorized atz = realClass.getAnnotation(Authorized.class);
    Audited audited = realClass.getAnnotation(Audited.class);
    // as sometimes we may want to prevent calls to authorization provider unless
    // explicitly invoked by developer
    SecurityDefinition definition = ((null == parent) ? new SecurityDefinition(featureConfig().shouldAuthorizeAnnotatedOnly(), featureConfig().failOnFailureIfOptional()) : parent.copyMe());
    definition.add(atn);
    definition.add(atz);
    definition.add(audited);
    if (!featureConfig().shouldAuthenticateAnnotatedOnly()) {
        definition.requiresAuthentication(true);
    }
    Map<Class<? extends Annotation>, List<Annotation>> customAnnotsMap = new HashMap<>();
    addCustomAnnotations(customAnnotsMap, realClass);
    SecurityLevel securityLevel = SecurityLevel.create(realClass.getName()).withClassAnnotations(customAnnotsMap).build();
    definition.getSecurityLevels().add(securityLevel);
    for (AnnotationAnalyzer analyzer : analyzers) {
        AnnotationAnalyzer.AnalyzerResponse analyzerResponse;
        if (null == parent) {
            analyzerResponse = analyzer.analyze(realClass);
        } else {
            analyzerResponse = analyzer.analyze(realClass, parent.analyzerResponse(analyzer));
        }
        definition.analyzerResponse(analyzer, analyzerResponse);
    }
    return definition;
}
Also used : Authenticated(io.helidon.security.annotations.Authenticated) Authorized(io.helidon.security.annotations.Authorized) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) AnnotationAnalyzer(io.helidon.security.providers.common.spi.AnnotationAnalyzer) Annotation(java.lang.annotation.Annotation) Audited(io.helidon.security.annotations.Audited) SecurityLevel(io.helidon.security.SecurityLevel) LinkedList(java.util.LinkedList) List(java.util.List)

Aggregations

Authorized (io.helidon.security.annotations.Authorized)3 SecurityLevel (io.helidon.security.SecurityLevel)2 Audited (io.helidon.security.annotations.Audited)2 Authenticated (io.helidon.security.annotations.Authenticated)2 AnnotationAnalyzer (io.helidon.security.providers.common.spi.AnnotationAnalyzer)2 Annotation (java.lang.annotation.Annotation)2 HashMap (java.util.HashMap)2 LinkedList (java.util.LinkedList)2 List (java.util.List)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 AuthorizationResponse (io.helidon.security.AuthorizationResponse)1 GET (jakarta.ws.rs.GET)1 Path (jakarta.ws.rs.Path)1 Application (jakarta.ws.rs.core.Application)1 Method (java.lang.reflect.Method)1 Invocable (org.glassfish.jersey.server.model.Invocable)1 ResourceMethod (org.glassfish.jersey.server.model.ResourceMethod)1