In GAE, when might a User not have an ID - google-app-engine

I am building a web app with go and GAE. I would like to use Google Accounts for authentication. The appengine/user package contains a type, User. I was planning on using ID property of User as the ancestor to descendent entities in the Datastore. However I'm confused by the comments in this section of documentation:
type User struct {
Email string
AuthDomain string
Admin bool
// ID is the unique permanent ID of the user.
// It is populated if the Email is associated
// with a Google account, or empty otherwise.
ID string
FederatedIdentity string
FederatedProvider string
}
Source: https://cloud.google.com/appengine/docs/go/users/reference#User
Under what circumstances might an email not be associated with a google account and therefore ID be empty?
I'm very new to go and GAE so please excuse my ignorance.

There are several key differences between email and id. E.g. "The app can also access a user ID that identifies the user uniquely, even if the user changes the email address for her account." Also "Every user has the same user ID for all App Engine applications."
Like ThunderCat said, if you use a Federated Login (OpenID was the only one supported, but is no longer), then you will not get a user id.
See the docs for more info.

Related

Reliably identifying a Teams guest user

I have a Microsoft Teams tab app and I'm using SSO for authentication. My users are both native and guests. My requirement is to show different screens depending on the type of incoming user (native/guest), so I have to identify the user type first. To ensure security, I first obtain the id token for the incoming user and then validate it first before identifying the user type. Is there any reliable way to identify the incoming user type with just the id token? I don't trust the info in tab context.
If you don't want to use Microsoft Graph API, you could add all the guest user into a security Group and include Groups claim in your token as instructed here. You just need to modify the "groupMembershipClaims" field in application manifest:
"groupMembershipClaims": "SecurityGroup"
Then the ID token will contain the Ids of the groups that the use belongs to like below :
{
"groups": ["1ce9c55a-9826-4e32-871c-a8488144bb32"]
}
You can also Add app roles in your application and receive them in the token.
You can use microsoft graph api(beta) get user.
https://graph.microsoft.com/v1.0/users/{id | userPrincipalName}
If the id token contains objectId of the user, just put the objectId as the parameter of this api. In the response, we can find an attribute userType. The value of this attribute could be Member or Guest.
If the id token doesn't contain objectId of the user, just contains email. We can also put it as the parameter in the graph api, but if the email is a guest user, the api will not get response data. So I asked you if it contains objectId in the comments.
By the way, the attribute userType just exists in the beta version of microsoft graph api but not exist in the v1.0 version microsoft graph api. So if you're not comfortable with beta version, I suggest to use Azure AD graph api(get user) instead of Microsoft graph api.
Hope it helps~

Create unique id per computer and use it as identifier when no user is logged in

I am trying to create a web app that would submit ratings to some articles. The backend is django and frontend is angularjs.
A rating is a model with the following properties: rater, value, and article
I would like to let anonymous users to submit ratings, in which case, the rater is null, but a sessionid is attached to the rating object to identify where this rating comes.
Currently, I am using the session module from django, and attaching session_key attribute to each rating object. However, this has issue that the session changed if a valid user is logged in and logged off.
What I would like to have is to have a unique identifier for each computer from which the rating is created, and attach this id to the object. So, as long as no user is logged in, the objects created by one computer, regardless of refreshing, rebooting, loggin+logout, etc., share the same identifier.
By doing this, my ultimate goal is to allow anonymous user using the App as if he/she is always logged in. In another word, each computer is a unique "implicit user" when no real user is logged in.
My question is that, is there a way to achieve this?
Thank you in advance!
LocalStorage
Anonymous users can't be tracked perfectly.
Best you can do in my opinion is using localStorage:
localStorage.setItem('anonymous-key', 'some-key-you-generated');
and then whenever no user is logged in:
var anonymousKey = localStorage.getItem('anonymous-key');
Persistence
Local storage stays saved until the user specifically clears it. Some browsers may also add a expiry date to your data for safety reasons.
See also: https://developer.mozilla.org/nl/docs/Web/API/Window/localStorage

How does Google+ Sign-In Compare to googleappengine.api.user signin?

The "user" submodule in Google App Engine uses "Google Account" rather than a "G+" sign-in. Are the base ID's the same? I'd like to associate their sign-ins with my own user records...
If you are asking the about the ids...
Specifically:
using
user = users.get_current_user()
returns a user object and that is not what you are referring (regarding to your comment)
The user_id() is what you where reffereing to for the users api:
user = users.get_current_user()
user.user_id()
From the Docs
If the email address is associated with a Google account, user_id returns the unique permanent ID of the user, a str. This ID is always the same for the user regardless of whether the user changes her email address.
If the email address is not associated with a Google account, user_id returns None.
Now from my experience my GoogleID according to user_id() is xxx8005350796570706xx and my Google Plus profile ID is 102445631084043565507 which are totally different. I also checked this with my apps and Google + known followers and found no similarity.
I would say they are not the same thing, but yes, you can associate them.
If you have used the support built into GAE (or Android) for basic Google accounts (User) to authenticate a user then you have their e-mail address which uniquely identifies their google account.
On Google+, use the email scope to gain access to their e-mail address:
https://developers.google.com/+/api/oauth#email-scopes
These e-mail addresses should match, so this will allow you to associate the Google and Google+ accounts. The downside to this method IMO is if you weren't already requesting the g+ email scope then you will have to add it.
You should create an own user model which will have info about registered users. Using users.get_current_user() you may take an e-mail address from user google account and login him to an app.

Should Google Appengine userId be treated as a secret?

Just wondering if the userId returned by calling the user.getUserId() should be treated as a secret, or can it be used in public URLs? for example, the profile page URLs look something like http://example.com/userprofile/11901930903930 where 11901930903930 is the Google generated userId on Appengine.
This is the function we are using to get the userId:
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
String id = user.getUserId();
Actually, I found this info on Google and the conclusion is that they should not be used publicly.
From Google:
Accessing Account Information
While a user is signed in to an app, the app can access the account's email address or OpenID identifier for every request the user makes to the app. The app can also access a user ID that identifies the user uniquely, even if the user changes the email address for her account.
The app can also determine whether the current user is an administrator (a "developer") for the app. You can use this feature to build administrative features for the app, even if you don't authenticate other users. The Go, Java, and Python APIs make it easy to configure URLs as "administrator only."
Note: Every user has the same user ID for all App Engine applications. If your app uses the user ID in public data, such as by including it in a URL parameter, you should use a hash algorithm with a "salt" value added to obscure the ID. Exposing raw IDs could allow someone to associate a user's activity in one app with that in another, or get the user's email address by coercing the user to sign in to another app.
Link to page

Do I need to insert one fake row in database?

I have few tables like example.
Users Books UsersBookPurchase
UID BookId UserId
UName Name BookId
Password Price
Email
This is fine. I am having my own login system but i am also using some 3rd party to validate like OpenID or facebook Authetication. My question is if the user is able to log in successfully using OpenID or facebook Authentication, what steps do i need to do i.e do i have to insert one fake row in Users table because if i do not insert how will integrity be maintained. I mean what user id should i insert in UsersBookPurchase when the person who has logged in using Facebook Authentication has made a purchase because the UserId is reference key from Users table. Please give me a high level overview of what i need to do because this is fairly common scenario.
Thanks in advance :)
Basically yes. Don't think of it as a fake row. What you should do is to create an actual user account based on the data provided by Facebook API (I am not that familiar with OpenID)
Facebook API will provide you with first and last name, email address, maybe some other data
Facebook does not have the concept of login name, users login by email address.
What you do is just create a new user from the data provided by API.
There are some things to watchout for: it is possible that user is already registered on your site. When you get data from Facebook you should search your own user table to see if the email address already belongs to your own registered user and it that case you can do some fancy things like mark that user as also having a facebook login.
If I were to do that, I'd abstracted login info into a separate table and have some sort of type in the User table. The type is used to identify what auth method is used, i.e. your own, Google, etc. If a user does select using alternative methods, you do need to have association but with a different type. But yes it is a new record.

Resources