I am currently using federated authentication via openid in appengine - using google, yahoo, myopenid as the providers
Had a question as to what I should be storing in my db to identify returning users.
I am currently storing user.getNickname() - (for google and yahoo this returns the users email address).
User user = userService.getCurrentUser();
String username = user.getNickname();
I use this to store and retrieve user specific data.
Is this the right way to proceed? Is the getNickName() unique? I see that User also has a user.getUserId() method and a user.getEmailId() method.
should I be using user.getUserId() instead?
getNickname() - don't use this.
getUserId() - this is logical, but the problem could be if users forget which identity they used with your site (I have multiple accounts with google, plus yahoo and facebook). This could lead to creating multiple account for one person. But then, some people want this. Also, this remains the same for Google users even if they change their email.
'getEmail()` - is actually similar to ID - uniquely identifies user. CAN be different then ID if users use alias email to log in.
Anyhow, when users log in for the first time you should present them with Account Details page (like SO does). Also, you should give users ability to aggregate identities into one account.
Related
I use google oauth2 to authorize users in my spring app. I can retrieve first and last name, email. But I also need to get their phone number and profession (jobTitle). How to retrieve phone number and profession from profile about me?
I used all scopes in application.yml- openid, email, profile, address, phone. There is no information in the (DefaultOidcUser) authentication.getPrincipal() object that I need. Maybe I need to use Google People API for it?
If you are already getting the names and email then all you need to do is add occupation and birthday to the personFields property its a coma separated field so the following should do it.
names,occupations,birthdays,email
The issue will probably be the scopes you are requesting. You will probably need to add.
https://www.googleapis.com/auth/user.birthday.read
https://www.googleapis.com/auth/user.organization.read
I'm working with telegram bot and i have this method to get user messages.
I need to find a way to get a link to the user who send this message
I saw there are this method, but i dont know how to connect them to a "link" to a profile
#Override
public void onUpdateReceived(Update update) {
update.getMessage().getFrom();
// i have: getFirstName(), getLastName() - not helping
// i have also getId() - but its a number how do i convert it to a link to telegram profile ?
}
Having username is optional on Telegram, setting it up means other people will be able to contact the user without knowing their phone number. Only users that chose their username in Telegram settings have a profile link, and the link is of the form https://t.me/<username>.
For ordinary messages, you can get the username via update.getMessage().getFrom().getUsername() and use it to create profile links, however, note that for many users this value will be empty (meaning they don't have a profile link).
Also, if you keep database of chat IDs, you can get usernames of the users via getChat Telegram API call. This can be useful because while usernames can be changed by the user any time (meaning their profile link will also change), chat ID of the user is constant over time and the getChat method will always provide you with the most recent information.
I am obtaining a kerberos ticket with the following code:
String client = "com.sun.security.jgss.krb5.initiate";
LoginContext lc = new LoginContext(client, new CallbackHandler() {
#Override
public void handle(Callback[] arg0) throws IOException, UnsupportedCallbackException {
System.out.println("CB: " + arg0);
}
});
lc.login();
System.out.println("SUBJ: " + lc.getSubject());
This code works fine, I get a subject that shows my user ID. The problem I'm having is now I need to know whether the user belongs to a certain group in AD. Is there a way to do this from here?
I've seen code to get user groups using LDAP but it requires logging in with a user/password, I need to do it the SSO way.
You cannot actually do this with the kind of ticket you get at login. The problem is that the Windows PAC (which contains the group membership information) is in the encrypted part of the ticket. Only the domain controller knows how to decrypt that initial ticket.
It is possible to do with a service ticket.
So, you could set up a keytab, use jgss to authenticate to yourself and then decrypt the ticket, find the PAC, decode the PAC and then process the SIDs. I wasn't able to find code for most of that in Java, although it is available in C. Take a look at this for how to decrypt the ticket.
Now, at this point you're talking about writing or finding an NDR decoder, reading all the specs about how the PAC and sids are put together, or porting the C code to Java.
My recommendation would be to take a different approach.
Instead, use Kerberos to sign into LDAP. Find an LDAP library that supports Java SASL and you should be able to use a Kerberos ticket to log in.
If your application wants to know the groups the user belongs to in order to populate menus and stuff like that, you can just log in as the user.
However, if you're going to decide what access the user has, don't log in as the user to gain access to LDAP. The problem is that with Kerberos, an attacker can cooperate with the user to impersonate the entire infrastructure to your application unless you confirm that your ticket comes from the infrastructure.
That is, because the user knows their password, and because that's the only secret your application knows about, the user can cooperate with someone to pretend to be the LDAP server and claim to have any access they want.
Instead, your application should have its own account to use when accessing LDAP. If you do that, you can just look up the group list.
I do realize this is all kind of complex.
I have a carpool website where users can log in through my DB and everything is working fine.
Once logged in, users can post advertisements for carpooling.
Now my need is for users to log in through Facebook. How is such a scenario handled?
Case 1: User is not registered with my DB and used Facebook credentials. I can show pages which are read-only, but say now the user wants to post an ad, what do I do in this case?
My DB is structured in such a way that the postAd table has user_id as foreign key, so in this case should I add a user with that email_id and a dummy password to allow them to post? Or how are such scenarios handled?
Case 2: If user logs in using Facebook do I need to search in my DB with that email id to find that user?
I am using Spring Security.
How does such a website generally work?
Thanks.
Take a look into Spring Social and Spring Social Facebook projects. They do:
For Case 1: there is Implicit sign up feature. You must provide ConnectionSignUp implementation that will be called when FB connection is established but there is no corresponding user in DB. You can create new DB user here.
For Case 2: there is a SignInAdapter interface (see ProviderSignInController's dependencies
chapiter). You can find DB user by userId then prepare autentication and inject it into SecurityContextHolder.
Genral idea: you can have multiple providers (FB, Twitter, etc...) but in any case each social profile will be matched to some Spring Security user (that will be used for authorization for example). If they match by userId then you can have one Spring Security user for multiple social accounts.
Advantage of this approach is that you will have more control over user profile (you can disable local user account even if FB account is active). You can use Facebook API from java code.
As a option 2 you can do FB login via JavaScript. Then implement two features for Case 1 and Case 2 manually (for example via custom filter). It may be more lightweight (depends on what features do you need).
Facebook Oauth provides a unique userid for each user. so, if a user sign in using facebook its better to store the details of the user such as id,name,email etc..in user table.so,you can use that userid as a primary key ... If the user already exists jsut skip this part and take them to post page..
I am Using Google App Engine for Java and I want to be able to share session data between subdomains:
www.myapp.com
user1.myapp.com
user2.myapp.com
The reason I need this is that I need to be able to detect if the user was logged in on www.myapp.com when trying to access user1.myapp.com. I want to do this to give them admin abilities on their own subdomains as well as allow them to seamlessly switch between subdomains without having to login again.
I am willing to share all cookie data between the subdomains and this is possible using Tomcat as seen here: Share session data between 2 subdomains
Is this possible with App Engine in Java?
Update 1
I got a good tip that I could share information using a cookie with the domain set to ".myapp.com". This allows me to set something like the "current_user" to "4" and have access to that on all subdomains. Then my server code can be responsible for checking cookies if the user does not have an active session.
This still doesn't allow me to get access to the original session (which seems like it might not be possible).
My concern now is security. Should I allow a user to be authenticated purely on the fact that the cookie ("current_user" == user_id)? This seems very un-secure and I certainly hope I'm missing something.
Shared cookie is most optimal way for your case. But you cannot use it to share a session on appengine. Except the case when you have a 3rd party service to store sessions, like Redis deployed to Cloud Instances.
You also need to add some authentication to your cookie. In cryptography there is a special thing called Message Authentication Code (MAC), or most usually HMAC.
Basically you need to store user id + hash of this id and a secret key (known to both servers, but not to the user). So each time you could check if user have provided valid id, like:
String cookie = "6168165_4aee8fb290d94bf4ba382dc01873b5a6";
String[] pair = cookie.split('_');
assert pair.length == 2
String id = pair[0];
String sign = pair[1];
assert DigestUtils.md5Hex(id + "_mysecretkey").equals(sign);
Take a look also at TokenBasedRememberMeServices from Spring Security, you can use it as an example.