Python-social-auth: do not reassociate existing users - django

I'm using python-social-auth to allow users to login via SAML; everything's working correctly, except for the fact that if a logged-in user opens the SAML login page and logs in again as a different user, they'll get an association with both of the SAML users, rather than switch login.
I understand the purpose behind this (since it's what you can normally do to associate the user with different auth services) but in this case I need to enforce a single association (ie. if you're logged in with a given SAML IdP, you cannot add another association for the same user with the same provider).
Is there any python-social-auth solution for this, or should I cobble together something (for instance, preventing logged-in users from accessing the login page)?

There's no standard way to do it in python-social-auth, there are a few alternatives:
Override the login page and if there's a user authenticated, then log them out first, or show an error, whatever fits your projects.
Add a pipeline function and set it in the top that will act if user is not None, you can raise an error, logout the user, etc.
Override the backend and extend the auth_allowed method in it return False if there's a valid user instance at self.strategy.request.user. This will halt the auth flow and AuthForbidden will be raised.

Related

How to get the idToken for a user without the user's password? AWS-Cognito

I am using AWS Cognito for the user management. I want to achieve a feature called "login as". Basically, the admin can use this feature to login as a specific user. The APIs I designed require idTokens for the authentication. So if I am able to get the idToken of a user, then I am able to login as the user.
Therefore, the question is "is there a way or Cognito API to get the idToken of a specific user without user's password?".
No this isn't possible and there is a very good reason for it. It ensures that the admin cannot simply log in as user and make changes under his name. Only the user is allowed to use his account. If that wasn't the case you would not have data integrity or non-repudiation

Using Firebase Auth with Django

I want to use firebase authentication for my django webapp. To achieve this, I think would I need to write a custom auth backend - is that right? I don't see any libraries that already do this - django-allauth looks like it comes pretty close as an alternative but I am interested in the phone number verification provided by firebase.
I'm also confused about what happens to the User model and functions like request.user or user.is_authenticated. Right now I use the authenticate and login functions - how does django know that a user is logged in via firebase? Would I still be creating a User model for every user?
Thanks
You can use Firebase Auth with any framework. You don't necessarily need to use custom auth. Typically, you would sign in the user on the client, get the ID token by calling firebase.auth().currentUser.getIdToken() and then pass the ID token to your server, verify it and parse its payload identifying the user ID and its other claims by using the Firebase Admin SDKs and then you can issue a session cookie identifying the user associated with that ID token.
On signout, you would clear that session cookie.
If you also need to persist that user on the backend after setting the session cookie, you can also use the Firebase Admin SDK to lookup a user identified by the user ID or just use the token claims to populate the user without any network call. You can populate that in the user model of associated framework if needed.
For more on session management, you can refer to this django documentation: https://docs.djangoproject.com/en/3.0/topics/http/sessions/

Cognito User Pools - Is it possible to create a custom sign up/in form for Facebook login?

I would like to use a Cognito User Pool for Facebook logins only, which may be possible using the built in login form, but I need to use my own.
Theoretically, when it comes to a custom form, it shouldn't be hard: after I receive a user object from FB, I bind the user and email attributes to the ones in my User Pool and I save it.
But what to do about the password field and future authentication? And here I have failed during my journey...
...
userPool.signUp('FoobarUser', '**password?**', attributeList, null, function(err, result){
...
While digging deeper into the docs, I tried to implement a Identity Pool (Federated Identities), managed to save user info in the form of datasets as well, but then I realised, querying these sets gonna be a huge pain if possible at all.
Maybe I'm failing to understand the concepts, I would be really thankful if someone could suggest a way to manage facebook logins in a nicely organised fashion using Cognito.
So here is what I understand from your query.
Setup
Link Facebook to userpool
The app client allows only Facebook login, no other providers allowed (not even Userpool)
On login, you want Facebook user's info to be automatically populated in your Userpool
You don't want to use Cognito's builtin UI but use your own
My 2 Cents
In your app client, just select Facebook
In your UI, have a login button. On clicking it should redirect to your userpool's authorization endpoint
https://your_domain.auth.us-east-1.amazoncognito.com/oauth2/authorize?redirect_uri=https://www.example.com&response_type=token&client_id=your_appclient_id
If you want to use your own UI with multiple providers, allow the same in Client and on clicking the appropriate button in your UI (say Facebook), redirect users to the authorize endpoint but append the identity_provider in the URL
https://your_domain.auth.us-east-1.amazoncognito.com/oauth2/authorize?redirect_uri=https://www.example.com&response_type=token&client_id=your_appclient_id&identity_provider=Facebook
If you want to see the names of all supported identity providers, use ListIdentityProviders API call
This way, all Facebook users will be automatically created in your userpool. Of course, their names will be random like Facebook_123jkjdwj but all their details will be correctly populated from the token as per your attribute mapping. As a plus, all auto-created users from a particular provider are added to an auto-created group 'Userpoolid_providername' eg. us_east_1_xxxx_Facebook.

Ping Identity switch user

Here at my company, we started using Ping Federate as our Identity provider, this is linked with the AD for user info and so on.
The login works via the OAuth page, and this works great, I can login, do things, then when my access_tokenexpires this get's refreshed and I can continue without the user even noticing it.
But now I got the request of one of the users if he could switch logins.
but this isn't possible, because when I click login, the popup of PingFederate that get's fired doesn't asks for the credentials, it just continues and uses the last credentials.
However when i clean my cookies and I login it asks for the credentials again, but I can't ask the users to clear all it's cookies whenever he wants to switch users.
I tried clearing the cookies of the PingFederate Domain when I logout, but no luck:
me.$cookies.remove('PF', {domain: 'federation.xxx.com'});
any body else has an idea what I can do to make this work?
You should be able to use PingFederate's logout features to achieve what you're after.
If you're using just the HTML Form Adapter to log in users, then you can configure a logout path in your adapter instance that you can ask users to go to to logout. See "Logout Path" here: https://support.pingidentity.com/s/document-item?bundleId=pingfederate-93&topicId=ttq1564003023121.html
Alternatively you could enable single logout (SLO) which will trigger a logout at all adapters or other authentication sources the user may have logged in to. For more details, see:
https://support.pingidentity.com/s/document-item?bundleId=pingfederate-93&topicId=php1564002958041.html
https://support.pingidentity.com/s/document-item?bundleId=pingfederate-93&topicId=pqn1564002990312.html

Create Custom Registration Pipeline Using python-social-auth

I have a django-based site that has private content and a small number of necessary users. I would like for everyone to use their Google account to authenticate using python-social-auth (PSA). I would therefore like to use the following process to add new users:
The new user visits the site and clicks on a "request access" button.
PSA would create a disabled user. The requesting user would be redirected to a page stating that access will be granted within 24 hours if approved.
The site admin would receive an email message notifying her of the request. If the new user is approved, then his account is enabled and the user is notified. If the request is not approved then the disabled account is deleted.
Once the user is enabled, he will login using the pipeline from this tutorial that only authenticates registered users. That part's easy. The hard part is figuring out how I'm going to register users but not authenticate them.
I tried extending the SOCIAL_AUTH_PIPELINE by adding a custom pipeline function that disables users if they're new. However, the pipeline continues to execute at that time, and it appears that it then tries to authenticate the new, disabled user. I say this because I'm redirected in my app to this URL:
http://myapp.com/accounts/login/?next=/
...which for me is a 404. This URL seems to be generated by PSA.
So here are my questions:
Is it possible for me to drop out of the SOCIAL_AUTH_PIPELINE and redirect my user to a "please wait for authorization" screen if they're a new user? I don't think that I can use a "partial pipeline" for this because I don't want to pick up the pipeline again later - I just want to "drop out" if this is a new user.
If that's not possible, then what's option B? Is it creating a custom pipeline that only handles registration? If so, then how would one do that?
You can keep your pipeline that flags the user as disabled, but also define this setting SOCIAL_AUTH_INACTIVE_USER_URL = "/wait-for-activation" (point it to the URL that shows the "wait for activation" page).