Netlify Identity and role based redirects woes

I am trying to password protect a whole site with Netlify identity and redirects (done via netlify.toml) and cannot get it working properly. I’ve tried to have as reduced of a test case as possible.

Test site
https://testrolesredirects.netlify.app

Site structure

contact/
  index.html
login/
  index.html
index.html
netlify.toml

netlify.toml file

[[redirects]]
  from = "/*"
  force = true
  status = 200
  conditions = {Role = ["admin"]}

[[redirects]]
  from = "/*"
  to = "/login/"
  force = true
  status = 302

I am always redirected towards the Netlify 404, although there is a login page at ./login/index.html

EDIT: what I want to achieve:

  • visitors with an admin role have access to all pages of the site
  • all other visitors should be redirected to the login page

Probably doing something wrong but cannot figure out what.

Hello Jerome,

Just a quick question.

Can you give an example of the expected behavior?

I’m looking at your redirects, and I’m not seeing a “to” in your first redirect… so it’s not clear what you want for Admins.

1 Like

Thanks for chiming in

As I understood from the docs, role based redirects do not need a ‘to’ key.

What I want to achieve:

  • full access to all pages of the site for visitors with an admin role
  • all other visitors are redirected to the login page

Seems the solution lies in using a 401 status for the second redirect rule. Everything seems to work if you change rules to the following:

[[redirects]]
  from = "/*"
  status = 200
  force = true
  conditions = {Role = ["admin"]}

[[redirects]]
  from = "/*"
  to = "/login/"
  force = true
  status = 401
1 Like

Hi @jeromecoupe, and thanks for sharing this solution

Do you know if a -paid- Netlify plan is required for such implementation?

Redirects are available on all tiers @Roneo.org

1 Like

Well. I spoke too soon.

The solution above does not quite work for me in the end. I thought I had it figured out but nope. The role based identity as a whole seems to behave strangely upon multiple logins/logouts for me.

[[redirects]]
  from = "/*"
  status = 200
  force = true
  conditions = {Role = ["admin"]}

[[redirects]]
  from = "/*"
  to = "/login/"
  force = true
  status = 401

Using Firefox / Chrome, head to
https://testrolesredirects.netlify.app

  1. Open a private window
  2. log in with Google
  3. Able to access both the home and contact page
  4. Log out
  5. Sometimes the contact page is still accessible
  6. Login
  7. The homepage is never accessible

Either I am doing something wrong with the redirects, or this functionality is a bit unpredictable in this current use case.

Please help if you can

2 Likes

Hi @jeromecoupe,

what is supposed to happen on the Contact and Homepage before to login?

I get an empty page with a few links, but not redirection to login page, even in Private mode with no Browser extension

Specified an “admin” role for you manually. Working on a function to do it automatically.

Specified an “admin” role for you manually. Working on a function to do it automatically.

Thank you. Now the access works as expected: the Contact and Homepage are accessible only while logged in. Tried 3 times, no problem seen

  1. Sometimes the contact page is still accessible

Maybe from the cache?

@Roneo.org Strange (but kind of nice). Did you try logging in and out during the same session as well ?

Hi @jeromecoupe,

What you’re trying, would not work. You’re trying to show all pages /* only if Admin role exists. At the same time, your /login/ page also falls under /* rule. Thus, you’d either have to move the login page to a different website, or protect a different path or try proxying the login page to itself like:

[[redirects]]
  from = "/login/"
  to = "/login/"
  force = true
  status = 200

[[redirects]]
  from = "/*"
  status = 200
  force = true
  conditions = {Role = ["admin"]}

[[redirects]]
  from = "/*"
  to = "/login/"
  force = true
  status = 401

So, this would make the login page accessible even without any user logging in.

1 Like

Hey thanks for stopping by @hrishikesh

What you say actually makes sense to me

but what I don’t understand is:

  • why does it works (apparently) with the previous .toml file ? I have seen a few inconsistencies on my end but an inaccessible login page has not been one of them.
  • how can the redirects described in this Netlify tutorial work ? Seems to me it has the same flaw you described above (from URL from the second redirect is also targeted by the first one).

Will try your solution and see if I get more consistent results on my end.

I am also trying to create a function to assign a role to a user logging in using Google. I found an example here but no luck so far.

I have read in the docs that identity-signup does not trigger what social login. Should I use identity-login or identity-validate and does it work the same way ?

Sorry for my barrage of questions … and thanks again for chiming in.

That’s interesting, I’d not expect it to work. If it does, I’m not sure why.

Are you talking about:

/testauth/* 200! Role=admin
/testauth/ /testlogin 404

If yes, then it works because /testlogin is a different page altogether not covered under /testauth/* directory. So you can visit that as RBAC is not controlling that path. It’s only affecting anything under /testauth/*.

Unfortunately, the events don’t work for any OAuth based login. But, if you’re using Netlify Identity Widget, you could get the login even and call your custom serverless function with the Authorization header and you would be able to access the user in context.clientContext.

Sorry, was talking about this article.

I thought that redirects would work in the order they are in inside netlify.toml and that a rule would be ignored if a condition is not met, thereby allowing the following one to be triggered.

Netlify generally parses redirect rules from top to bottom. As a result, it will always use the first match it finds when processing redirect rules and ignore any subsequent matches. In the example therefore, if a role has not been set, the user is redirected via the second rule to the /login page.

In my case, what I was trying to say is:

  • Allow every page on the site to be viewed if the user has an “admin” role
  • If that condition is not met, redirect every user to the /login/ page.

So your suggestion with social login is that I use webhooks and serverless functions the way it is described in this article ?

That works because it only matches the URLs with query parameters:

query = {path = ":path"}

You’re 100% correct. But, you’re setting a rule to allow everything under /* only for the Admin role. Your login page also exists under /*. So, you’re into an infinite loop - to see the login page you need to have the Admin role, but to get the Admin role, you need to access the login page. I hope you’re seeing my point.

So your redirect rule is correct, just that, login page cannot be inside the path that’s gated by RBAC. So if you gate something like /foo/*, login page must be somewhere else - could be an entirely different website (not really, it’s just an exaggeration to make a point).

1 Like

Thanks. I grok that part now I think.

So your suggestion for social login (Google) is that I use webhooks and serverless functions the way it is described in this article ?

That article shows an example of the kind of serverless functions you can build. Depending on your use case, it might help. But as I said before, you won’t be able to use those functions to automatically trigger on Identity events. So you’d have to manually make a call to foo.netlify.app/.netlify/functions/bar/ with the data you need to change.

Ok thanks. One thing at a time. First Gated content ! Thanks for your help