Adding basic auth to all routes and how to seal() properly

I’m trying to add basic authentication to all my routes and I’m noticing odd behavior. Looking around it seems that because I concat() the routes that it’s trying to next route afterwards which I don’t want. I then decided to seal() the routes but when I do that my second route api isn’t even available.
I feel like I’m uncovering a misunderstanding I have with creating apis using akka http. All the examples I’ve seen use concat() but I don’t understand the benefit of trying other routes when the client wanted to use that specific route even if it failed.

public Route getRoutes() {
        return concat(createScheduledRecordingRoute().seal(), getScheduledRecordingRoute().seal());

private final Function<Optional<ProvidedCredentials>, Optional<String>> basicAuthenticator = providedCredentials ->
            providedCredentials.filter(creds -> creds.identifier().equals("USERNAME") && creds.verify("PASSWORD")).map(ProvidedCredentials::identifier);

private Route createScheduledRecordingRoute() {
        PathMatcher1<UUID> pathMatcher = apiV1Root.slash(CAMERAS).slash(uuidSegment()).slash(SCHEDULED_RECORDING);
        return path(pathMatcher,
                (cameraId) -> authenticateBasic("secure", basicAuthenticator,
                        (username) ->
                                post(() ->
                                        entity(Jackson.unmarshaller(objectMapper, ScheduledRecordingView.class),
                                                scheduledRecordingView -> complete(apiHandler.createScheduledRecording(cameraId, scheduledRecordingView)))

private Route getScheduledRecordingRoute() {
        PathMatcher2<UUID, UUID> pathMatcher = apiV1Root.slash(CAMERAS).slash(uuidSegment()).slash(SCHEDULED_RECORDING).slash(uuidSegment());
        return path(pathMatcher,
                (cameraId, scheduledRecordingId) -> authenticateBasic("secure", basicAuthenticator,
                        (username) -> get(() -> complete(apiHandler.getScheduledRecording(cameraId, scheduledRecordingId)))));

I was under the impression that concat() was used for when you had a series of routes you want to serve and not if you wanted them chained together if one fails.

The examples online for Java and Akka-http are a bit limited so I apologize if I’m doing something the wrong way. I have two routes, one to create a ScheduledRecording, one to retrieve them. I want to use basic auth on each route.

If I seal the first route, then the second route is dead I noticed.

What am I missing here? Thank you very much.

Hi @dleacock,

when sealing a route you are no longer allowing concat to fallback to the alternative routes. I would first try removing that seal invocation from the code.

I’m not sure I understood why you needed sealing in the first place, though.