Help with http.login and Google Auth

Hi. I am new to Caddy. I love it so far.

I have a question about http.login and Google Auth.

Here is what I am trying to do:

  1. I want to protect all of my content in /project
  2. I want to use Google oAuth
  3. I want to choose a specific domain name to authorize (@example.com)
  4. If someone is not in that domain, I want to show them a “sorry” message
  5. If someone is in that domain, I want to send them to /project

My current caddyfile looks like this [1].

Issues I am confused about.

  • I don’t know how to redirect from /project to /login when someone is not authorized. I get the little Google button when I’m on /login, but not at /project as an unathorized user. Is that even possible, or should I just accept that I’ll have an ‘401 unathorized’ message?
  • I don’t know how to set the domain (@example.com) or to add users, one by one (would rather not) to my caddyfile.
  • When I login successfully, I am still getting ‘401 unathorized’ in the project folder. I actually used to get a generic logout page, but I can’t seem to get it back? Not sure what setting that was, but this was also a problem in that I was not in the /project directory, but rather on this generic “welcome matt@example.com” page.

Basically, I am asking for a Google Oauth caddy file example to protect all content, or content in a subdirectory, with a domain, or list of users.

Thanks

[1] My caddyfile

localhost:80, example.com {
 gzip
 log access.log
 markdown /pro

jwt {
    path /project
    except /favicon.ico
}

 login {
    success_url /project
    cookie_name blah
    cookie_http_only true
    google client_id=0000,client_secret=9999,scope=https://www.googleapis.com/auth/userinfo.email
 }
}

http.jwt has a subdirective redirect that you can use to configure a 303 redirect for unauthorised users.

Looks like you can supply a user file that matches a domain/email/username etc. to specific levels of access the user will receive when they return from OAuth.

GitHub - qvest-digital/loginsrv: JWT login microservice with plugable backends such as OAuth2, Google, Github, htpasswd, osiam, ..

I’m sorry, I’m a little confused by this one - you’re getting 401s the moment you log in? And when you refer to a generic logout page, do you mean a little “You’ve been logged out” notice, or something else?

Thanks for the help so far. The redirect subdirective works. Great.

I created a userfile as follows [1]. This does not seem to work in that when I go to my /project directory, I am redirected back to the root directory. If I go to /login (after authenticating) I see “welcome” and I can logout - but if I go to /project I get redirected back to /. There seems to be no way to see my content? I took the user-file [2] directive out of my caddyfile and the same behavior occurs.

When we get this working - my next question is about how my user-file roles can be used.

caddyfile excerpt:

jwt {
    path /project
    except /favicon.ico
    redirect /
 }

login {
    success_url /project
    cookie_name feranti
    cookie_http_only true
    google client_id=ffff,client_secret=ddddd,scope=https://www.googleapis.com/auth/userinfo.email
 }

user-file (doesn’t work with or without it)

- domain: gmail.com
  origin: Google
  claims:
    role: user

Same behavior with this caddyfile (references userfile):

jwt {
    path /project
    except /favicon.ico
    user-file users.yml
    redirect /
 }

login {
    success_url /project
    cookie_name feranti
    cookie_http_only true
    google client_id=ffff,client_secret=ddddd,scope=https://www.googleapis.com/auth/userinfo.email
 }

I believe the user file has to be configured for http.login, since that’s the plugin based on loginsrv that takes that file I linked the documentation for, but I can’t seem to find a subdirective for it in the Caddy plugin README.

Perhaps the author (CCing @smancke) will be able to elaborate on whether this is possible?

I’m wondering if this is some kind of caching issue perahps, although it shouldn’t be. According to the docs, the JWT plugin only returns a 303 redirect if it would have otherwise returned a 401 or 403 status, so being successfully authenticated should preclude any 303s.

I believe that these:

jwt {
path /project
except /favicon.ico
redirect /
}

Should be:

jwt {
path /project
except /favicon.ico
redirect /login
}

To use a YAML file for user claims you need to use the parameter -user-file.

Then follow these instructions:

Please confirm if everything is good.

In Addition to that, what @magikstm wrote …

  • The user-file users.yml should be user_file users.yml and has to be part of the login {} directive.
  • The origin: Google hast to be origin: google (lower case)

To get the right behaviour out of the JWT plugin, you have to understand the way the both plugins work together by the claims defined in the JWT-token. You should inspect the token after login (browser console and https://jwt.io/) and check if everything works as expected.

In your configuration, the JWT plugin allows access to every person, which is able to login. (So every google user). The userfile is optional and works the way, that every user, where the criterias in the userfile match (e.g. coming from google and having the domain gmail.com in the mail address) gets the additional claims added to the JWT token. With this it is possible to add arbitrary contens to the token and check them with allow and deny statements in the jwt plugin.

Here is another example, where access to the whole domain is only allowed to one user:

  jwt {
    path /
    redirect /login
    allow email sebastian.mancke@example.com
  }

  login {
    success-url /main
    google client_id=XXXXXX,client_secret=YYYYYYY,scope=https://www.googleapis.com/auth/userinfo.email
  }
2 Likes

I love how responsive you are. Thanks so much for taking the time.

Ok. Haven’t tried the user_file yet, but I will. Thanks for the help.

Next question. If someone logs in and is not allowed (they authenticate, but they are not allowed access), could I modify the template to show a message like “sorry, you don’t have access, try to login with an approved google account.”

So, let’s say that my users.yml file looks like this [1]. What would the conditional statement look like in the template? Something like this [2]?

[1] users.yml

- domain: example.org
  origin: Google
  claims:
    role: user

- claims:
    role: unknown

[2] template file

<!DOCTYPE html>
<etc....>

      {{if .role == "unknown"}}
       "sorry, you don't have access, try to login with an approved google account
      {{end}}

      {{if .Authenticated}}

         {{template "userInfo" . }}

      {{else}}

        {{template "login" . }}

      {{end}}

      <!-- your footer -->
</body>
</html>

Ok, I seem to have gotten things working nicely. Here are my files for future reference. The only outstanding question I have is about the “if” statement and how I can check the role.

caddyfile:

localhost:8081, example.com {
 gzip
 log mysite/access.log
 root mysite
 markdown / {
 ext .md
 template template.html
 }

 jwt {
    path /
    redirect /login
    allow role user
    except /strapdown
 }

 login {
    success_url /project
    google client_id=dddd,client_secret=ddd,scope=https://www.googleapis.com/auth/userinfo.email
    user_file mysite/users.yml
    template login.html
 }

}

users.yml

- domain: example.com
  origin: google
  claims:
    role: user

- claims:
  role: unknown
1 Like

Hey, coll, that it works!

It is currently not possible to refer the claims in the login form template.
At them moment, the only solution for this would be to access the JWT client-side by Javascript (you have to set cookie_http_only=false for that).

I have this set up using allow rules in the jwt plugin, which doesn’t require a users.yml. For example:

jwt {
	path /
	redirect /login
	except /strapdown
	allow domain example.com
}

login {
	success_url /project
	google client_id=dddd,client_secret=ddd,scope=https://www.googleapis.com/auth/userinfo.email
	template login.html
}

You can also allow individual email addresses using allow sub in the jwt plugin.

If someone logs in with an incorrect email address, it’ll just show the logged in page without letting you access any other pages. This should be editable using the template html file, which appears to be defined in loginsrv/login_form.go at master · tarent/loginsrv · GitHub
That uses if statements to determine if the user is logged in and display a message appropriately.

To determine which role is being applied, you might be able to use .UserInfo.Domain as defined in loginsrv/user_info.go at master · tarent/loginsrv · GitHub

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.