Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gitlab oauth support #305

Merged
merged 20 commits into from
Aug 9, 2020
Merged

Gitlab oauth support #305

merged 20 commits into from
Aug 9, 2020

Conversation

miksir
Copy link

@miksir miksir commented Jun 4, 2020

@bugy
Copy link
Owner

bugy commented Jun 4, 2020

Wow, that's mighty! thanks a lot!

Just a couple of questions before I start digging into the code:

1

dump - filename where to persist user/group information
session_expire_min - user inactivity time before logged out

do you think it's GitLab specific? Or it can be re-used for all authentications?

2

dump

does it have default value? I think it would be ok to save it to temp folder by default

3

Do you store user information anywhere, to perform additional requests (for ttl, for example). I tried avoiding to store any user information, to reduce user credentials (or tokens) exposure.
So if someone gets access to Script server or the user cookie, they still won't be able to access 3rd party auth services (i.e. google, gitlab or ldap)

@miksir
Copy link
Author

miksir commented Jun 4, 2020

do you think it's GitLab specific? Or it can be re-used for all authentications?

both implemented only for gitlab auth at this moment
session_expire_min can be useful for all auth providers and can be implemented overriding new is_active method from Authenticator
dump - depend on where we want to to store some session data... I decided to store in memory and dump to file, but may be someone will decide to use secure cookie or database :)
if your question about naming - its ok to rename

does it have default value? I think it would be ok to save it to temp folder by default

nope, if dump missed - it's totally disabled and restart of app will logout all users

Do you store user information anywhere, to perform additional requests (for ttl, for example). I tried avoiding to store any user information, to reduce user credentials (or tokens) exposure.
So if someone gets access to Script server or the user cookie, they still won't be able to access 3rd party auth services (i.e. google, gitlab or ldap)

Well, for sure it's stored in memory
dump store it in file, but this options can be skiped

Also I think to implement special type of authentication without group support, in this case I can ask read_user scope from gitlab, it's read only, so user api token can be used only for reading some information.

I will think how to hide data in dump file. May be to encrypt it with key passed via ENV. But this problem is wider... for example, how to stop accessing logs because user can remove logs with script.

@miksir
Copy link
Author

miksir commented Jun 4, 2020

Added information about dump to wiki page

@bugy
Copy link
Owner

bugy commented Jun 4, 2020

Thanks for your answers!

if your question about naming - its ok to rename

no, not really. My question was about reusing it for all authentication :) If it would be easily achieved in future

I will think how to hide data in dump file. May be to encrypt it with key passed via ENV.

If an attacker has access to the server, he can access the key as well. So I don't think it would be much more secure.
I think it's fine to store it as it is, but feature users should be aware of this potential security risk.

But this problem is wider... for example, how to stop accessing logs

I think if the server is compromised, there is not much you can do about server data itself. But if you dump user credentials (or gitlab user token), then the attacker would be able to access GitLab as well.

What kind of user data/credentials do you store in the moment? By the way, did you consider storing it in user secured cookies?
For the current authentication mechanism, I perform user authentication once, and if it's successful, I just store that it was authenticated and discard any other credentials/tokens. It has some drawbacks (e.g. if user groups got updated in the meantime or the user is removed), but I thought, that doesn't happen so often and I can provide stronger security guarantees in this case.

PS sorry if these questions sound as critique (or request for changes), it's definitely not intended this way. I'd like to discuss and understand the chosen approach. And we can try to find all potential flaws and benefits, so Script server usage will be secure (first) and convenient.

@miksir
Copy link
Author

miksir commented Jun 4, 2020

What kind of user data/credentials do you store in the moment?

Only OAuth2 token but with API scope, so it's a lot. There is read_user scope, its safe, but can't fetch user's groups with it.

By the way, did you consider storing it in user secured cookies?

well, it's possible, can do it

I think if the server is compromised, there is not much you can do about server data itself.

I am thinking about "script wrapper" for run script with sudo or in docker container. It can help to restrict access to script server files.

…rmation

+ group_support on/off, is off - read_user scope used
@miksir
Copy link
Author

miksir commented Jun 4, 2020

Gitlab oauth key now stored in secure cookie. For better safety now it's possible to auth with read_user gitlab scope - it's read only scope with very limited access, but gitlab groups will not be used.

dump -> state_dump_file,
ttl -> auth_info_ttl,
session_expire_min -> session_expire_minutes
Copy link
Owner

@bugy bugy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, impressive work! Thanks a lot!

I have a couple of questions (since I don't know how Gitlab auth works) and some suggestions about extracting common code

src/auth/auth_gitlab.py Outdated Show resolved Hide resolved
src/auth/auth_gitlab.py Outdated Show resolved Hide resolved
src/auth/auth_gitlab.py Outdated Show resolved Hide resolved
src/auth/auth_gitlab.py Outdated Show resolved Hide resolved
src/auth/auth_gitlab.py Outdated Show resolved Hide resolved
src/tests/auth/test_auth_gitlab.py Outdated Show resolved Hide resolved
src/tests/auth/test_auth_gitlab.py Outdated Show resolved Hide resolved
web-src/src/login/login.js Show resolved Hide resolved
src/web/server.py Outdated Show resolved Hide resolved
src/tests/auth/test_auth_gitlab.py Outdated Show resolved Hide resolved
@bugy
Copy link
Owner

bugy commented Jun 5, 2020

Hi @miksir, I checked the PR. At the moment there is a lot of duplication between Google oauth and GitLab oauth. What do you think about extracting common part to some generic OauthAuthenticator? And then let google and GitLab implementations implement only the part, which is different?

I think it would be fine if you move your new logic (with logout, dump, ttl, etc.) to this common class as well, so it will be used by google authenticator also.

@miksir
Copy link
Author

miksir commented Jun 5, 2020

Both is OAuth, but lot of small difference. logout, dump, ttl needs only because user validity recheck implemented, but in Google OAuth not. I see what you want but it's require massive refactoring of Authenticator :(

@bugy
Copy link
Owner

bugy commented Jun 5, 2020

but lot of small difference. logout, dump, ttl needs only because user validity recheck implemented

But all of those can be used for google as well, cannot they? The only difference is how you parse the response. For Gitlab you check the state (and probably groups), but for google you just get email field.
If there is an error or email is missing, the use is also inactive and can/should be logged out

@miksir miksir closed this Jun 9, 2020
@miksir miksir reopened this Jun 9, 2020
@bugy
Copy link
Owner

bugy commented Jun 9, 2020

Hi @miksir should I try to help you with the refactoring? I should have time on Thursday, I think.

@miksir
Copy link
Author

miksir commented Jun 10, 2020

I pushed some changes. Please, check unresolved with my answers - do you need more info? I will try to refactor unit tests today.

If you want to refactor google oauth too - yes, I need you help because I has other priority tasks from users.

MiksIr added 7 commits June 10, 2020 13:16
@bugy
Copy link
Owner

bugy commented Jun 11, 2020

Hi @miksir, I'm working on the refactoring, hope to finish until end of the day
Are you going to do any changes here, today? Because it would be quite hard to merge them

@miksir
Copy link
Author

miksir commented Jun 11, 2020

Nop, no changes planned. But I rebased branch (no changes, just rebase), so rebease too :)

@bugy
Copy link
Owner

bugy commented Jun 12, 2020

Hi @miksir I did common behaviour extraction to a separate class. Unfortunately, I couldn't test Gitlab auth, so if you could check (and probably fix it), it would be cool.

I'll still work on unit tests

I also changed current behaviour a bit:

  1. I'm not storing user state anymore. If it becomes disabled, I just remove user's state completely and he has to re-login. I thought, that storing a state was a bit redundant
  2. A user is validated only during his validate_user phase and only this user
  3. Access_token is stored only if auth_info_ttl is enabled
  4. Dump file is taken every 30 seconds, to avoid potential clashes when multiple users are being updated simultaneously. I think, I'll also add checksum checking, to avoid unnecessary writes, if nothing has changed
  5. Custom OAuth implementations have to define fetch_user_info and fetch_groups (i.e. how to load the data). Everything else is managed by a common class
  6. I changed user state from a dictionary to a dedicated class. For me, it's easier to work in PyCharm, when the IDE knows about existing fields and can suggest/validate them :)
  7. The dump file structure was changed a bit, to address 1. and 6., so I believe you would have to delete the dump file before testing

I think I went to deep and probably you won't recognize your code anymore 😅 But what do you think about the new flow?

@miksir
Copy link
Author

miksir commented Jun 12, 2020

  1. I'm not storing user state anymore. If it becomes disabled, I just remove user's state completely and he has to re-login. I thought, that storing a state was a bit redundant
  1. Dump file is taken every 30 seconds, to avoid potential clashes when multiple users are being updated simultaneously. I think, I'll also add checksum checking, to avoid unnecessary writes, if nothing has changed

Sorry, I am confused :) Dump and storing user state was the same :) It was dump of users state.

@bugy
Copy link
Owner

bugy commented Jun 12, 2020

I meant state['state'] :) Like 'active', 'error', etc.

@miksir
Copy link
Author

miksir commented Jun 12, 2020

I C. Great work. It's look like you can refactor ldap auth too :)

@bugy
Copy link
Owner

bugy commented Jun 13, 2020 via email

@miksir
Copy link
Author

miksir commented Jun 13, 2020

One question: for session expiry you chose minutes, do you have a real case for it? Usually it's days. I would think that hours would be more than enough

Well, may be someone want 30 min session. So just got minimal usable. But, imho, best way is to use human readable form. Like 30m or 1h30m

@bugy
Copy link
Owner

bugy commented Jun 13, 2020

Hi @miksir I'm done with the refactoring.

Let's keep the session behaviour as per your implementation for now: I realized, that using cookie expire time would have different behaviour: the time wouldn't be reset on user actions and would just measure time after login.

If gitlab auth is still working for you, and you are fine with my changes, we can merge the PR

@miksir
Copy link
Author

miksir commented Jun 15, 2020

Will check today. But i think you can register on gitlab.com and add application here https://gitlab.com/profile/applications for test

@bugy
Copy link
Owner

bugy commented Aug 9, 2020

Alright, I finally tested it and it seems to work :)
Thanks a lot @miksir for the great work!

@bugy bugy merged commit e39523f into bugy:master Aug 9, 2020
@bugy bugy added this to the 1.16.0 milestone Aug 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants