Skip to content

Commit 8785d56

Browse files
committed
Add readme
1 parent b919980 commit 8785d56

File tree

4 files changed

+126
-20
lines changed

4 files changed

+126
-20
lines changed

plume-web-jersey/README.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,103 @@ public void waitAsync(@Suspended final AsyncResponse asyncResponse) {
137137
}
138138
```
139139

140+
Requests authorization
141+
----------------------
142+
Multiple authorization provider are implemented.
143+
For all provider, the HTTP header `Authorization` is used to fetch the authorization value.
144+
145+
### Basic authorization
146+
This feature is provided by the `BasicAuthenticator` class.
147+
Sample usage:
148+
```java
149+
@Path("/example")
150+
@Tag(name = "example", description = "Manage exemple web-services")
151+
@Consumes(MediaType.APPLICATION_JSON)
152+
@Produces(MediaType.APPLICATION_JSON)
153+
// Since we are performing authorization in the resource, we can mark this API as public
154+
@PublicApi
155+
@Singleton
156+
public class ExampleWs {
157+
private final BasicAuthenticator<String> basicAuthenticator;
158+
159+
@Inject
160+
public ExampleWs() {
161+
this.basicAuthenticator = BasicAuthenticator.fromSingleCredentials(
162+
"my-username",
163+
"my-password",
164+
// Message displayed to the user trying to access the API with a browser
165+
"My protected API"
166+
);
167+
}
168+
169+
@GET
170+
@Path("/test")
171+
@Operation(description = "Example web-service")
172+
public Test test(@Context ContainerRequestContext requestContext) {
173+
basicAuthenticator.requireAuthentication(requestContext);
174+
175+
return new Test("Hello world");
176+
}
177+
}
178+
```
179+
180+
One sample valid request: `curl -u 'my-username:my-password' 'http://localhost:8080/api/example/test'`
181+
182+
### API Key authorization
183+
This feature is provided by the `BearerAuthenticator` class.
184+
Sample usage:
185+
```java
186+
@Path("/example")
187+
@Tag(name = "example", description = "Manage exemple web-services")
188+
@Consumes(MediaType.APPLICATION_JSON)
189+
@Produces(MediaType.APPLICATION_JSON)
190+
// Since we are performing authorization in the resource, we can mark this API as public
191+
@PublicApi
192+
@Singleton
193+
public class ExampleWs {
194+
private final BearerAuthenticator bearerAuthenticator;
195+
196+
@Inject
197+
public ExampleWs() {
198+
this.bearerAuthenticator = new BearerAuthenticator("my-bearer-token");
199+
}
200+
201+
@GET
202+
@Path("/test")
203+
@Operation(description = "Example web-service")
204+
public Test test(@Context ContainerRequestContext requestContext) {
205+
bearerAuthenticator.verifyAuthentication(requestContext);
206+
207+
return new Test("Hello world");
208+
}
209+
}
210+
```
211+
212+
One sample valid request: `curl -H 'Authorization: Bearer my-bearer-token' 'http://localhost:8080/api/example/test'`
213+
214+
### Resource authorization based on annotation
215+
This feature is provided `AuthorizationSecurityFeature` and works with any authentication system.
216+
For example using bearer auth:
217+
- In the `JerseyConfigProvider` file, declare the feature with the annotation used for resource identification: `config.register(new BearerAuthenticator("my-bearer-token").toAuthorizationFeature(BearerRestricted.class));`
218+
- In the `JerseyConfigProvider` file, register if needed the annotation used in the `RequireExplicitAccessControlFeature`: `config.register(RequireExplicitAccessControlFeature.accessControlAnnotations(PublicApi.class, BearerRestricted.class));`
219+
- Use the annotation in a resource definition:
220+
```java
221+
@Path("/example")
222+
@Tag(name = "example", description = "Manage exemple web-services")
223+
@Consumes(MediaType.APPLICATION_JSON)
224+
@Produces(MediaType.APPLICATION_JSON)
225+
// The new annotation that will ensure the authorization process before granting access
226+
@BearerRestricted
227+
@Singleton
228+
public class ExampleWs {
229+
@GET
230+
@Path("/test")
231+
@Operation(description = "Example web-service")
232+
public Test test() {
233+
return new Test("Hello world");
234+
}
235+
}
236+
```
237+
238+
### Permissions based authorization
239+
TODO to details

plume-web-jersey/src/main/java/com/coreoz/plume/jersey/security/basic/BasicAuthenticator.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package com.coreoz.plume.jersey.security.basic;
22

3-
import com.coreoz.plume.jersey.security.AuthorizationVerifier;
4-
import lombok.extern.slf4j.Slf4j;
5-
3+
import com.coreoz.plume.jersey.security.AuthorizationSecurityFeature;
64
import jakarta.ws.rs.ClientErrorException;
75
import jakarta.ws.rs.ForbiddenException;
86
import jakarta.ws.rs.container.ContainerRequestContext;
97
import jakarta.ws.rs.core.HttpHeaders;
108
import jakarta.ws.rs.core.Response;
119
import jakarta.ws.rs.core.Response.Status;
10+
import lombok.extern.slf4j.Slf4j;
1211

1312
import java.lang.annotation.Annotation;
1413
import java.nio.charset.StandardCharsets;
@@ -62,13 +61,17 @@ public static BasicAuthenticator<String> fromSingleCredentials(String singleUser
6261
// API
6362

6463
/**
65-
* Provide an {@link AuthorizationVerifier} from the basic authenticator to provide annotation based request authorization using {@link com.coreoz.plume.jersey.security.AuthorizationSecurityFeature}
66-
* @param annotation The annotation that will be used to identify resources that must be authorized. For example {@link BasicRestricted} can be used if it is not already used in the project for another authorization system
67-
* @return The basic authenticator corresponding {@link AuthorizationVerifier}
68-
* @param <A> The annotation type
64+
* Provide a {@link AuthorizationSecurityFeature} from the bearer basic that can be used in Jersey
65+
* to provide authentication on annotated resources.
66+
* @param basicAnnotation The annotation that will be used to identify resources that must be authorized. For example {@link BasicRestricted} can be used if it is not already used in the project for another authorization system
67+
* @return The corresponding {@link AuthorizationSecurityFeature}
68+
* @param <A> The annotation type used to identify required basic authenticated resources
6969
*/
70-
public <A extends Annotation> AuthorizationVerifier<A> toAuthorizationVerifier(A annotation) {
71-
return (authorizationAnnotation, requestContext) -> requireAuthentication(requestContext);
70+
public <A extends Annotation> AuthorizationSecurityFeature<A> toAuthorizationFeature(Class<A> basicAnnotation) {
71+
return new AuthorizationSecurityFeature<>(
72+
basicAnnotation,
73+
(authorizationAnnotation, requestContext) -> requireAuthentication(requestContext)
74+
);
7275
}
7376

7477
/**

plume-web-jersey/src/main/java/com/coreoz/plume/jersey/security/bearer/BearerAuthenticator.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.coreoz.plume.jersey.security.bearer;
22

3-
import com.coreoz.plume.jersey.security.AuthorizationVerifier;
4-
import com.coreoz.plume.jersey.security.basic.BasicRestricted;
3+
import com.coreoz.plume.jersey.security.AuthorizationSecurityFeature;
54
import com.google.common.net.HttpHeaders;
65
import jakarta.ws.rs.ForbiddenException;
76
import jakarta.ws.rs.container.ContainerRequestContext;
@@ -25,20 +24,25 @@ public BearerAuthenticator(String bearerToken) {
2524
}
2625

2726
/**
28-
* Provide an {@link AuthorizationVerifier} from the bearer authenticator to provide annotation based request authorization using {@link com.coreoz.plume.jersey.security.AuthorizationSecurityFeature}
29-
* @param annotation The annotation that will be used to identify resources that must be authorized. For example {@link BasicRestricted} can be used if it is not already used in the project for another authorization system
30-
* @return The basic authenticator corresponding {@link AuthorizationVerifier}
31-
* @param <A> The annotation type
27+
* Provide a {@link AuthorizationSecurityFeature} from the bearer authenticator that can be used in Jersey
28+
* to provide authentication on annotated resources.
29+
* @param bearerAnnotation The annotation that will be used to identify resources that must be authorized. For example {@link BearerRestricted} can be used if it is not already used in the project for another authorization system
30+
* @return The corresponding {@link AuthorizationSecurityFeature}
31+
* @param <A> The annotation type used to identify required bearer authenticated resources
3232
*/
33-
public <A extends Annotation> AuthorizationVerifier<A> toAuthorizationVerifier(A annotation) {
34-
return (authorizationAnnotation, requestContext) -> verifyAuthentication(requestContext);
33+
public <A extends Annotation> AuthorizationSecurityFeature<A> toAuthorizationFeature(Class<A> bearerAnnotation) {
34+
return new AuthorizationSecurityFeature<>(
35+
bearerAnnotation,
36+
(authorizationAnnotation, requestContext) -> verifyAuthentication(requestContext)
37+
);
3538
}
3639

3740
public void verifyAuthentication(@NotNull ContainerRequestContext requestContext) {
3841
String bearer = parseBearerHeader(requestContext.getHeaderString(HttpHeaders.AUTHORIZATION));
3942

4043
if (bearer == null || !MessageDigest.isEqual(authenticationSecretHeader.getBytes(), bearer.getBytes())) {
41-
throw new ForbiddenException("Invalid bearer header: " + bearer);
44+
logger.warn("Invalid bearer header: {}", bearer);
45+
throw new ForbiddenException();
4246
}
4347
}
4448

plume-web-jersey/src/main/java/com/coreoz/plume/jersey/security/permission/PermissionFeature.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import jakarta.ws.rs.container.ResourceInfo;
99
import jakarta.ws.rs.core.FeatureContext;
1010
import lombok.extern.slf4j.Slf4j;
11-
import org.glassfish.jersey.server.internal.LocalizationMessages;
1211

1312
import java.lang.annotation.Annotation;
1413
import java.util.Collection;
@@ -37,7 +36,7 @@ private static <A extends Annotation> AuthorizationVerifier<A> makeAuthorization
3736
) {
3837
return (authorizationAnnotation, requestContext) -> {
3938
if(!authorize(requestPermissionProvider, requestContext, permissionAnnotationExtractor.apply(authorizationAnnotation))) {
40-
throw new ForbiddenException(LocalizationMessages.USER_NOT_AUTHORIZED());
39+
throw new ForbiddenException();
4140
}
4241
};
4342
}

0 commit comments

Comments
 (0)