What does a "User needs to accept terms of service" 401 error mean? - box-api

We will occasionally get this error message:
User needs to accept terms of service
when making API calls. Replaying the calls will work later on. What does this error message mean exactly and is there a way we can avoid it?

I encountered this when a user was created (by an admin or via the API), an email was sent to the user and the user needs to confirm their email and agree to the ToS, and then I tried to impersonate that user via the API before the user agreed to the ToS.

Related

CrossClient Authorization between Server and Gmail Addon

Background:
This is about using a Gmail Addon created using Google App Script.
When the user installs the addon, there is the OAuth Consent Screen where user provides his consent to allow the "Product name shown to users" (as configured in the OAuth Screen) to allow the access specified.
Now, I read : https://developers.google.com/identity/protocols/CrossClientAuth
which states :
When a user grants access to your app for a particular scope, the user
is looking at the user consent screen, which includes project-level
product branding that you set up in the Google API Console. (For
information about setting up the consent screen, see Setting up OAuth
2.0 in the API Console help.) Therefore, Google considers that when a user has granted access to a particular scope to any client ID in a
project, the grant indicates the user's trust in the whole application
for that scope.
Now, I have a server web component (a lambda) (belonging to the same product) that needs access to the user's email same access that the user provided after installing the addon ("Authorized Access" button).
Question(s) :
Is there a way to have cross-client (a backend server and a gmail addon) in my case to have the backend to just get access to user's data without triggering additional (basically whatever the user has provided consent to)?
Note: Using an additional authorization screen triggered manually using the GAS OAuth library I was able to get the "Auth Code" which I pass to the server using which the server now has access to the consented data (we have used the same client id and secret). However, the problem with this approach is :
User gets 2 emails about the permissions granted. Addon and Manually triggered flow.
User has to authorize the gmail addons for first access and then another which I trigger manually.
Even if there was a way I could get the "Auth Code" when the user installs the addon that would also do.
Apologize in advance there is a lot of scattered documentation and though I went through many it is likely I may have missed something.
We only issue one authorization code (refresh token) in exchange for one user authorization/approval. Your app can get new access tokens on android or web without a user approval. But if it needs a refresh token again, user still need to approve the request.
So if the addon can talk to your server, you could give it a short lived access token or will need to user authorization.

Service now api how to comment as specific user

I'm working on a project that consumes Service Now API (Rest). To do so our client has registered us as a user in order to login and make all service calls we need to. This project has an interface where users can login once they have an account on Service Now as well, the username they type to log in has nothing to do with service now by the way, but later they associate theirs service now users to it. They can do some operations through this interface, where all of them are done using the integration user/pass not their service now users theirselves, even because they do not need to share their passwords with us. But it's needed to track the correct user to register on service now and I'm in trouble specifically about commenting on an incident. The endpoint to comment is the following :
http://hostname/api/now/table/incident/{sys_id}
where request body is a json object just as simple as :
{
"comments": "My comment is foo bar"
}
but when this comment is registered on Service Now it is under integration user instead the user which commented. Is there any way I could keep a specific user, considering I already have the user id on Service Now ready to inform it on the request the way it should be.
I tried reading Service Now documentation but had no clue how to solve it, altought I've found something about impersonate
This is happening because you're being proxied through the "Integration User" instead of your own account. As long as this is the case, your comments are going to be attributed to the Integration User.
I can think of two ways to fix this issue.
Ask the client to log you into their system directly as a user.
Implement a special API (Scripted REST API, available in Geneva or later) that allows you to identify the Incident and enter the comment, and then the script forges the comment on your behalf, attributing authorship correctly.
The first solution can be expensive due to possible additional licensing costs.
The second solution will require a willing client to devote 2-3 hours of development time, depending on the programmer.
Firstly, you need an integration user with suffient rights. Our integration user has suffient rights out of the box, but your story could be different. A quick check is to try impersonate as other user using menu.
Login as integration user to ServiceNow instance.
Go to https://{instance}.service-now.com/nav_to.do
Click on username at top right corner. This is a drop down.
There should be at least three menu items: "Profile", "Impersonate User", and "Logout". If you do not have "Impersonate User" in this menu, your integration user miss some permissions. Contact system administrator if you miss this menu item to configure appropriate permissions.
Then you need to find sys_id of user that you want to impersonate. For example:
https://{instance}.service-now.com/api/now/table/sys_user?sysparm_query=user_name={username}&sysparm_fields=sys_id
If you have suffient privileges, you could invoke the folling endpoint with sys id of user that you want to impersonate:
HTTP POST to https://{instance}.service-now.com/api/now/ui/impersonate/{user_sys_id} with body "{}" and content type "application/json". You need to provide HTTP basic authentication to this query as your integration user.
The response code on success is 200. The response body could be ignored. The interesting result of this response is a set of cookies for impersonated user in response headers. These cookies could be used for subsequent REST API calls until they expire. Use some HTTP rest client dependent method to capture them and to provide them to next calls.
For Apache HTTP Client (Java), I'm creating http client context using:
HttpClientContext context = HttpClientContext.create();
context.setCookieStore(new BasicCookieStore());
Pass thing context to impersonation request and to subsequent API calls until I get 401 reply, after that I'm reaquiring cookies. Setting new cookie store is important, as otherwise some default cookies store is used.
Two things to note:
This API looks like internal one, so it could change at any time. If it happens, look for what "Impresonate User" menu item does, and repeat it youselves.
ServiceNow permissions are quite fine-grained, so the target user could lack permissions to perform operation. In some cases, if there is no permission to update the field the operation PATCH on object returns reponse 200, but field is not updated. This introduces a surprising mode of failure when you use impersonation.

Posible pitfalls when switching from Gmail smtp to Gmail rest api

Google offers two systems for accessing Gmail. IMAP and SMTP and a the Gmail rest api Gmail - Scope for SMTP is https://mail.google.com/. However with Gmail rest API, just the required scope (like send, modify) can be used.
What are the main differences between the implementation of these two for sending an email? I've been using SMTP to send the mails without any issues but since that involves having a bigger scope for OAuth2, I want to know if there are any possible risks involved in moving to the API approach.
Users.messages: send says there's a restriction on attachment size.
This method supports an /upload URI and accepts uploaded media with
the following characteristics:
Maximum file size: 35MB Accepted Media MIME types: message/rfc822
Are there any other differences that I should know about if I start using Gmail APIs instead of using SMTP connection for OAuth2.
Also, what is the reasoning behind providing full access as the only possible scope for SMTP/IMAP?
Note: I only requirement is the ability to send emails.
Using SMTP you are directly accessing the mail server located at mail.google.com. SMTP servers have been around since the 60's they don't have the ability to limit what access you have. When you log in you have full access to do what ever the mail server in question is capable of. To login to the SMTP server you need the login (most often email address) and password of the account you wish to access. Drawback to using the SMTP to connect to Gmail is that if the user changed the password you would then loose access. This day in age it is also considered by most to be bad practice for third party developers to be storing a users login and password in your system. For example: I would never give any application access to my login and password to Google. How could you ever prove to me that your system is secure? If your hacked so am I.
Now on to Oauth2. Oauth came about sometime around 2005 when people wanted to be able to access APIs without having to do something stupid like
http://awsom.api.com?login=xxx&password=XXX
If memory services it was originally created for the twitter API developers wanted to be able to access their users twitter account without having to store their login in and password. Again the main problem with this was the developer in question would then have full access to a users twitter account and if the user or the developer changed the password things would break.
So they created OAuth. The main features with OAuth are:
You can limit access you give an application: (readonly, read write)
Password change does not affect access
No sharing account credentials with developers of third party apps
So the main point for me as a developer using Oauth with any Google API would be not having to store the login and password of my users and not being affected by a password change. My users would probably say not having to share their login with me and being able to give my application limited access to their account.
Now back to Gmail. Google made a change about two months ago any refresh token(oauth2) that was created using a Gmail scope will automatically expire when the user changes their password. To my knowledge this is only Gmail. so that removes point number two from the features of oauth.
Which should you use is really up to you, assuming you need to be able to send emails. Then limiting access to read only in your application isn't something you need (point one). However in my opinion from a security standpoint I would never ask my users to give me their login and password and would always choose oauth2. Yes SMTP works, will Google shut it down, probably not users have always been given access to the direct SMTP server of their email provider its how applications like outlook work.
as for OAuth support with SMTP unfortunately I haven't done much research into that guess I need to read RFC 4422 . If you can use OAuth with SMTP servers then again I guess the question would have to come down to speed is it faster to access the SMTP server or the REST API server? I can really think of no differences. Attachments with the Rest API can be tricky. I may do a bit more digging on the subject.

Azure API Management Sign Up Stuck In Process

I'm using Azure API Management and I have a user who tried to sign up but never got the "validation" email. Let's just assume the email is not recoverable. Unfortunately, I have no way to reset that user's email address. The API Management framework knows that the email already exists but I have no visibility to that user's profile until they validate the account. At that point I can manage their account but, until then, they are in-limbo.
If the user tries to re-sign up or even if I send an invite, we get an error that says. "Email already exist"
Any pointers?
The confirmation request will expire in 2 days, so if the user tries again after 2 days, the "email already exist" error should go away.
Meanwhile, we are currently working on a feature to allow Admins to delete unconfirmed users from the Management Console.
In addition to allowing admins to remove unconfirmed users we added the ability for users to re-send confirmation email.

box.com api OAuth authentication

Either I'm dense, or the docs assume I already know what they're telling me, but I need some clarification on doing authentication for a box.com app. I really don't understand whate's going on. As I read it:
the app running on the user's machine sends a request to Box, including all the little secrets (Which aren't all that secret any more if the user knows how to read the code).
The user is directed to the Box login page, which then sends the user to my server (with no page specified) attaching an authentication code.
The app somehow magically gets that code back from my server and sends a request to Box for the access token.
Box sends the access token to my server?
The app again magically gets the access token from my server and sends its APT requests.
Obviously I got lost somewhere.
And, why do I have to have a server involved in the process? The article on making a JavaScript app refers to a direct request for a token. Is there documentation on that somewhere?
You register your application on Box
After registration you receive clientId and clientSecret once on Box website
You hardcode your credentials somewhere in your application
First time your application needs to access Box API it should redirect user to https://www.box.com/api/oauth2/authorize, specifying your clientId, clientSecret and redirectURI as parameters. About redirectURI see below.
The box.com website opens. User enters his own credentials in the web form on box.com
User allows your application to access his files via API on the box.com website
Box redirects user back to you application using redirectURI specified before. One of the parameters to this request is "code". This is a very short-lived (30 seconds) access code that is only aligable for obtaining real access token.
During next 30 seconds your application should make another call to Box API to next URL: https://www.box.com/api/oauth2/token, specifying the previously obtained code. If everything was correct, your application receives an access_token, a refresh_token and "expires" values.
Now your application can make requests to Box API, specifying access_token every time
access_token expires in number of seconds, specified in "expires" field. It should be about 3600 seconds or 1 hour. Each time your application sees that access_token has expired, it should make another request to Box with the refresh_token and obtain a fresh access_token for another 1 hour.
refresh_token itself expires in 14 days
Note: if you develop a desktop application, then you should open browser for user on the step 4, redirectURI should be something like http://127.0.0.1:8080/Callback and you should run a small webserver just to catch the redirect with the code as in step 7.
Box requires that you specify a redirect_uri in your application's profile, and it must be an HTTPS URL.
As a result, it is not possible to use box with what google's oauth2 documentation calls "Client Side" or "Installed" applications, only "Web Server Applications" are allowed. Web Server applications do not have the secret leaking problem, because only the server knows the secret. You can pass the access token from your server to javascript on the client after
the oauth transaction is complete, if you want the client to make api requests directly.
In your question you are not totally clear in what you are actually trying to produce.
I however suspect that you are trying to write a client application what needs to authenticate to box using the OAUTH2 solution they have delivered in API V2.
If this is for an IPhone for example BOX has a great example of how to handle it.
In a WinForm application you would need to capture the resulting code sent back by box in the browser1.isnavigating event.
Windows console application you register a custom URI registration to collect the code.
Neither of these need to be registered in the API developers Application on box as you would pass the redirect required in the request to box.
If this does not point you in the right direction and your writing a .NET app then post again and I will try to clarify a little more.
Box requires some form user interaction which is short sighted in my opinion but try a web service that simulates a user interaction which then you can save/pass the token to your application to sync up with the Box "Cloud".