You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shiro.apache.org by Steinar Bang <sb...@dod.no> on 2021/12/06 16:19:35 UTC

Shiro: possible to configure part of the unauthenticated URLs to return 401 instead 302?

Is it possible to configure a part of the URL space to return 401
instead of 302 when unauthenticated?

I would like to avoid 302 redirects for calls to the REST API.

Thanks!


- Steinar

Re: Shiro: possible to configure part of the unauthenticated URLs to return 401 instead 302?

Posted by Steinar Bang <sb...@dod.no>.
>>>>> Brian Demers <br...@public.gmane.org>:

> You can also use `@RequireRoles("myapprole")` annotation instead of
> the permission one.

> I think the problem you might be running into is the
> `PassThruAuthenticationFilter` doesn't have a "permissive" option, so
> it's likely redirecting on that fitler.

Ok.  I can't remember why I'm using that one, but it is the one that had
the behaviour I desired once upon a time... ah! The comment says why:
  // Using the PassThruAuthenticationFilter instead of the default authc FormAuthenticationFilter
  // to be able to do a redirect back "out of" authservice to the originalUrl

It's because of my usage of shiro to something other than authentication
inside of a java webapp.  I use it to provide cookie authentication to
nginx and across multiple web applications.

> To work around this, you could use the form auth filter, or create
> your own filter that instead of redirecting returns a 401
> https://github.com/apache/shiro/blob/0c0d9da2d81a4b24de6e02bc1c8a2ad1b5ef32d7/web/src/main/java/org/apache/shiro/web/filter/authc/PassThruAuthenticationFilter.java#L49-L56

> Bind your new fitler to `/api/**`

> Does that help?

Yes, I think so, thanks!

But it will require some thought and experimentation...

But since I won't do redirects on the /api/* paths, there is no need for
the PassThruAuthentication behaviour here, so I could use the regular
authc filter for this path.

Re: Shiro: possible to configure part of the unauthenticated URLs to return 401 instead 302?

Posted by Brian Demers <br...@gmail.com>.
You can also use `@RequireRoles("myapprole")` annotation instead of
the permission one.

I think the problem you might be running into is the
`PassThruAuthenticationFilter` doesn't have a "permissive" option, so
it's likely redirecting on that fitler.
To work around this, you could use the form auth filter, or create
your own filter that instead of redirecting returns a 401
https://github.com/apache/shiro/blob/0c0d9da2d81a4b24de6e02bc1c8a2ad1b5ef32d7/web/src/main/java/org/apache/shiro/web/filter/authc/PassThruAuthenticationFilter.java#L49-L56

Bind your new fitler to `/api/**`

Does that help?

On Tue, Dec 7, 2021 at 2:14 PM Steinar Bang <sb...@dod.no> wrote:
>
> Side note: shiro-jaxrs and RequiresPermissions annotations may be a way
> to accomplish what I want to do.
>
> But what I really wanted was something simpler: avoid 302 redirects for
> the part of URL space used by ajax calls (since 302s are handled by the
> browser and never reach the ajax code waiting for a response).
>
> I'm completely OK with having access to the endpoint managed by the
> shiro filter.  Returning 401 until the frontend logs a user in is
> completely OK.  I don't need the fine grained permission control offered
> by shiro-jaxrs and @RequirePermissions. I just want to avoid 302 on the
> REST operations.
>
> Should I add a shiro feature request for this? (I imagine I'm not the
> only one wanting something

Re: Shiro: possible to configure part of the unauthenticated URLs to return 401 instead 302?

Posted by Steinar Bang <sb...@dod.no>.
Side note: shiro-jaxrs and RequiresPermissions annotations may be a way
to accomplish what I want to do.

But what I really wanted was something simpler: avoid 302 redirects for
the part of URL space used by ajax calls (since 302s are handled by the
browser and never reach the ajax code waiting for a response).

I'm completely OK with having access to the endpoint managed by the
shiro filter.  Returning 401 until the frontend logs a user in is
completely OK.  I don't need the fine grained permission control offered
by shiro-jaxrs and @RequirePermissions. I just want to avoid 302 on the
REST operations.

Should I add a shiro feature request for this? (I imagine I'm not the
only one wanting something 

Re: Shiro: possible to configure part of the unauthenticated URLs to return 401 instead 302?

Posted by Steinar Bang <sb...@dod.no>.
>>>>> Brian Demers <br...@public.gmane.org>:

> That should work, keep us posted!

Ok, 2 years, 8 weeks, and 5 days has passed, but now I finally got
around to it, and I can report it worked perfectly:
 1. User with the required role is logged in: a POST to the API gets 200 OK
 2. User withot the required role is logged in: a POST to the API gets 403 FORBIDDEN
 3. Not logged in: a POST to the API gets 401 UNAUTHORIZED

Not a 302 FOUND in sight! :-)

Both the 401 and 403 responses are handled as errors by axios, so the
following redux saga fires off a SAVE_MODIFIED_PICTURE_FAILURE instead
of a SAVE_MODIFIED_PICTURE_RECEIVED 
 https://github.com/steinarb/oldalbum/blob/feb8a3e9d8125be012b5c76db36e907807f841a7/oldalbum.web.frontend/src/main/frontend/src/sagas/modifyPictureSaga.js#L18
(my problem with 302 was that the 302 redirected to the login page and
the HTML login page was returned with a 200 OK, but didn't parse well as
JSON, so that a SAVE_MODIFIED_PICTURE_RECEIVED with an empty data
blanked out existing values).

What I did, was:
 1. Add a maven dependency to shiro-jaxrs
     https://github.com/steinarb/oldalbum/blob/feb8a3e9d8125be012b5c76db36e907807f841a7/pom.xml#L52
     https://github.com/steinarb/oldalbum/blob/feb8a3e9d8125be012b5c76db36e907807f841a7/oldalbum.web.api/pom.xml#L75
    (scope compile causes it to be added to the bundle's auto-generated,
    attached, feature repository, so that the bundle will be loaded at
    runtime in karaf)

 2. Override the init() method of the Jersey ServletContainer base
    class of the servlet, to do the same thing as the Application here:
     https://shiro.apache.org/jaxrs.html#example
    (the org.glassfish.jersey.server.ResourceConfig class extends
    javax.ws.rs.core.Application)
     https://github.com/steinarb/oldalbum/blob/feb8a3e9d8125be012b5c76db36e907807f841a7/oldalbum.web.api/src/main/java/no/priv/bang/oldalbum/web/api/OldAlbumWebApiServlet.java#L44

 3. Add a @RequiresUser and a @RequiresRoles annotation to the top of
    the JAX-RS resource that needs autentication (the resource handling
    the REST endpoints that does modification of the database)
     https://github.com/steinarb/oldalbum/blob/feb8a3e9d8125be012b5c76db36e907807f841a7/oldalbum.web.api/src/main/java/no/priv/bang/oldalbum/web/api/resources/AlbumentryResource.java#L37

 4. Use anon for all of the REST API in the shiro.ini
     https://github.com/steinarb/oldalbum/commit/feb8a3e9d8125be012b5c76db36e907807f841a7

Thanks for the pointers, Brian!

And sorry for the late feedback, but better late than never! :-)

Re: Shiro: possible to configure part of the unauthenticated URLs to return 401 instead 302?

Posted by Brian Demers <br...@gmail.com>.
That should work, keep us posted!

On Wed, Dec 8, 2021 at 11:37 AM Steinar Bang <sb...@dod.no> wrote:
>
> >>>>> Brian Demers <br...@public.gmane.org>:
>
> > Cookies will get processed, but if you are using some other form of
> > header based auth they wouldn't be (unless you a corresponding filter
> > configured)
>
> In this case I'm thinking of what's set by the
> PassThruAuthenticationFilter when authenticating the frontend.
>
> Will enough what PassThruAuthenticationFilter sets get through the anon
> filter, to make the @RequireRoles or @RequirePermissions in shiro-jaxrs
> work?
>
> Thanks!
>
>
> - Steinar

Re: Shiro: possible to configure part of the unauthenticated URLs to return 401 instead 302?

Posted by Steinar Bang <sb...@dod.no>.
>>>>> Brian Demers <br...@public.gmane.org>:

> Cookies will get processed, but if you are using some other form of
> header based auth they wouldn't be (unless you a corresponding filter
> configured)

In this case I'm thinking of what's set by the
PassThruAuthenticationFilter when authenticating the frontend.

Will enough what PassThruAuthenticationFilter sets get through the anon
filter, to make the @RequireRoles or @RequirePermissions in shiro-jaxrs
work?

Thanks!


- Steinar

Re: Shiro: possible to configure part of the unauthenticated URLs to return 401 instead 302?

Posted by Brian Demers <br...@gmail.com>.
Cookies will get processed, but if you are using some other form of
header based auth they wouldn't be (unless you a corresponding filter
configured)

On Tue, Dec 7, 2021 at 5:04 PM Steinar Bang <sb...@dod.no> wrote:
>
> Question:
>
> when I do this:
>
> > [main]
> > authc = org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter
> [snip!]
> > [urls]
> > /api/** = anon
> > /** = authc, role[myapprole]
>
> don't I then use a different filter than PassThruAuthenticationFilter
> for /api/?
>
> Can I do this and still use @RequiredPermission() and @RequiredRole() on
> the resources?  Or will the necessary cookie and headers not be present?

Re: Shiro: possible to configure part of the unauthenticated URLs to return 401 instead 302?

Posted by Steinar Bang <sb...@dod.no>.
Question:

when I do this:

> [main]
> authc = org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter
[snip!]
> [urls]
> /api/** = anon
> /** = authc, role[myapprole]

don't I then use a different filter than PassThruAuthenticationFilter
for /api/?

Can I do this and still use @RequiredPermission() and @RequiredRole() on
the resources?  Or will the necessary cookie and headers not be present?

Re: Shiro: possible to configure part of the unauthenticated URLs to return 401 instead 302?

Posted by Steinar Bang <sb...@dod.no>.
>>>>> Brian Demers <br...@public.gmane.org>:

> This post is a little old (dependency wise), but it should still be accurate.

Hm... I'm on shiro-1.7.0 currently, so the mentioned shiro-jaxrs should be available...?
(and currently on jersey 1.8.4, if that matters...?)

> See the bit about the "permissive" filter.
> https://stormpath.com/blog/protecting-jax-rs-resources-rbac-apache-shiro

Interesting!

> If you go this route, you will need to ensure you are checking access
> another way: annotation, another filter, etc.

Ie. the idea is to let everything to the API through untouched and then
use annotations to set permissions on the jersey resources, and then let
shiro-jax handle access control?

Is it possible to split the handling?
I.e. to use regular handling on the frontend and shiro-jaxrs and
annotations on the REST API?

Will something like this work as expected?

[main]
authc = org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter
shiro.loginUrl = /login
shiro.unauthorizedUrl = /unauthorized

[urls]
/api/** = anon
/** = authc, role[myapprole]

"work as expected" means:
 1. /** will be handled with redirect to /login when not logged in
 2. /api/** will pass through, but shiro-jaxrs handling will work

Or will shiro-jaxrs be affected by the shiro.ini config and let
everything though, whatever the @RequiresPermission() says?

Thanks!


- Steinar

Re: Shiro: possible to configure part of the unauthenticated URLs to return 401 instead 302?

Posted by Brian Demers <br...@gmail.com>.
This post is a little old (dependency wise), but it should still be accurate.

See the bit about the "permissive" filter.
https://stormpath.com/blog/protecting-jax-rs-resources-rbac-apache-shiro

If you go this route, you will need to ensure you are checking access
another way: annotation, another filter, etc.

On Mon, Dec 6, 2021 at 11:20 AM Steinar Bang <sb...@dod.no> wrote:
>
> Is it possible to configure a part of the URL space to return 401
> instead of 302 when unauthenticated?
>
> I would like to avoid 302 redirects for calls to the REST API.
>
> Thanks!
>
>
> - Steinar