When creating a token for an offline app, what happens to the token when access is revoked for the user who created it? - xero-api

I asked this in Xero's developer forums, but it looks like Xero are not supporting developers any more. Quite a few questions going unanswered. I thought this might be a better place to discuss with developers.
We created an app for a client prior to the Oauth2 change, so we completely rejigged it using the suggested new Oauth2 workflow where we login to Xero, grant access to the Xero account, and then store the renewal token in a database. Then routinely refresh the token. We did this via the client granting full access to their Org for our Xero account so they didn't have to go through the process of doing the initial connection.
Now that they have this connection setup, the customer wants to remove our access to their Xero org. And have done so. But since then we are seeing grant_type errors from any attempt to contact Xero.
Am I right in thinking that once access is revoked to an org, any token created by that user now has no access? And if so, what is the exact suggested plan here? Create a new account just for API usage that is never revoked? I don't think I've come across an API used for building M2M applications that requires the non-technical client to actually connected to the API itself.

If a user wants to disconnect your API app from connecting to their org and they revoke it through the Settings < Connected Apps < Disconnect button then that just revokes that specific access_token from making any future calls and disables the refresh_token from creating new valid access_token's.
Might need a bit more context to guide you to the best solution for your scenario, but if you were to re-authenticate from the user's perspective and re-save the newly generated OA2 token_set your API access for that user/org should be reinstated.

Related

How to maintain connectivity to Office365 with Mailkit without reauthenticating user each email sent

Some background information which could be helpful to other potential solutions. My organization uses my windows login to also access other software applications such as office365 (outlook online and outlook desktop app). This password is required to be updated every so often and all other applications update together all at once so they are all interconnected. I am assuming there is some identity server or something which is tying it all together for authentication. So I am building a ASP.NET Core application which a user logs in via different username and password that is stored in a SQL Server. My web application will soon require email functionality so the users can send emails after doing some function in the application. Therefore I have put together the following code from examples online which does in fact work and let me send emails through our office365 email accounts using our organization official username(assigned email address for the mailkit below) and passwords.
public void SendEmail()
{
// create email message
var email = new MimeMessage();
email.From.Add(MailboxAddress.Parse("myEmail#something.org"));
email.To.Add(MailboxAddress.Parse("recipient#something.org"));
email.Subject = "my Subject";
email.Body = new TextPart(TextFormat.Plain) { Text = "Email sending has been integrated!" };
//send email
using var smtp = new SmtpClient();
//office 365
//Office 365 does not support NTML (windows authentication) so we need some sort of interation with an API to not store usernames and passwords.
smtp.Connect("smtp.office365.com", 587, SecureSocketOptions.StartTls);
smtp.Authenticate("myEmail#something.org", "passwordDuh");
smtp.Send(email);
smtp.Disconnect(true);
}
Since my web application does not connect to this identity server for authentication (really do not have much information on this internal service for my organization and my web application is more of a side project for my team) I have to manually insert the username and password into the code above. For testing purposes I have just added them in but I need to automate this or improve the code to be up to best practices. Therefore, I have thought of the following solutions but I am not sure of the feasibility of some of them or if there is a better/more appropriate solution:
Forgo my current username and password setup in the SQL DB and authenticate users at login with this identity server indirectly by using the current line below for mailkit and use in my login class to check the credentials against office365 (which probably uses our organizations identity server since the passwords are all linked with it):
smtp.Authenticate("myEmail#something.org", "passwordDuh")
And if it succeeds to authenticate then I know the office365 credentials are correct and I will create my authentication token as usual that I send for the users frontend to log into the site and stay logged in. My issue with this is I am not sure how I could stay connected to office365 so that I could send emails later on in the application use. It is unclear if this connection and authentication technique expires after some time if the user hasnt sent an email for an hour or so.
Use a similar approach to 1 but if I cannot keep the connection open I can take the user password if authenticated with office365 and encrypt the password with a salt then store in session a session variable. From everything I have read on stack answers seem to advice against storing passwords in plaintext in session and say to encrypt it but the responses tend to also give the sense this is still not adviced to keep even an encrypted password in session.
Figure out some way to get a token from office365 when a user logs into my site and authenticates with office365. Reading some solutions regarding getting an access token from office365 seems to indicate you need to have the application registered in azure and approved by an admin. This seems more like an api token to access their api for my application itself and not using a users username and password. I am less familiar with this solution so forgive me for my ignorance but I have tried researching this quite a bit and seems to not lead me to anything I can use unless I am missing something.
My organization uses my windows login to also access other software applications such as office365 (outlook online and outlook desktop app).
Oof. That's not a good practice.
Forgo my current username and password setup in the SQL DB and authenticate users at login with this identity server indirectly by using the current line below for mailkit and use in my login class to check the credentials against office365 (which probably uses our organizations identity server since the passwords are all linked with it):
I'm not sure I understand how this would work. Are you saying that when a user connects to your web service, they would have to provide their login credentials that you would then send to office365 to test to see if authentication is successful?
>_<
That seems like a hack that I doubt security experts would approve of since it requires passing along naked passwords.
A better approach (although I am no security expert, so take this with a grain of salt) might be to use an OAuth2 code flow to authenticate with office365 which would give you an access token that could then be used later for sending mails via MailKit's SmtpClient.
My issue with this is I am not sure how I could stay connected to office365 so that I could send emails later on in the application use. It is unclear if this connection and authentication technique expires after some time if the user hasnt sent an email for an hour or so.
You'd have to spawn a thread or something that would periodically call SmtpClient's NoOp() method (or NoOpAsync()). to keep the connection alive, although even this could eventually fail to keep that connection open eventually, so you'd have to be able to deal with a situation where the connection gets dropped.
Use a similar approach to 1 but if I cannot keep the connection open I can take the user password if authenticated with office365 and encrypt the password with a salt then store in session a session variable. From everything I have read on stack answers seem to advice against storing passwords in plaintext in session and say to encrypt it but the responses tend to also give the sense this is still not adviced to keep even an encrypted password in session.
Yea, not a great approach. You'd obviously still have to have a way to decrypt the password again and therein lies the weakness.
Figure out some way to get a token from office365 when a user logs into my site and authenticates with office365. Reading some solutions regarding getting an access token from office365 seems to indicate you need to have the application registered in azure and approved by an admin. This seems more like an api token to access their api for my application itself and not using a users username and password. I am less familiar with this solution so forgive me for my ignorance but I have tried researching this quite a bit and seems to not lead me to anything I can use unless I am missing something.
They are talking about an OAuth2 access token and this is most likely the correct way to go.
I wrote up some documentation on how to do this with a native desktop app, but I never got around to documenting this for an ASP.NET (or ASP.NET Core) web app. You can find the docs for the desktop app here: https://github.com/jstedfast/MailKit/blob/master/ExchangeOAuth2.md
Someone recently submitted ASP.NET web app docs for similar GMail authentication which can be found here: https://github.com/jstedfast/MailKit/blob/master/GMailOAuth2.md#authenticating-an-aspnet-web-app-with-the-oauth2-client-id-and-secret
You'll likely need to read the docs and find some samples for ASP.NET Core usage, but it's possible to do.

What is the correct way to use OAuth for mobile and website consuming my own API?

I have a question more related to the way OAuth 2 is working but since using IdentityServer to implement OAuth I think it's relevant. I could not find an answer anywhere.
I'm building a website and a mobile app that consumes my own API. Each user of my app will have a username and password, that will give him access to the app/website and though the API to his information.
I'm not sure about the right way to handle the flow for user login:
On the website I have my own designed login form. I don't want to move the user to my auth server to login, and then have him approve the information he gives - he is the user on my system - I have access to all information - kida like facebook has a login and access to the informatio - they don't ask what you're willing to give them. So is implicit really the way for this?
On the mobile app I also have a login form and now I read here (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-native-apps-10) that the OAuth approach is to have the login in a WebView?? Doesn't look like facebook login is in a WebView on their mobile app.
The approach I was first lookin at is the Resource Owner. Users will login, get the token and the refresh token and can start working against my APIs. But storing my client_id and secret on the mobile app? on the website javascript files? doesn't feel right. I can of course make a call to an API that will mask those and be a proxy to the login process... but... (read #4).
In the future I would like to allow access for third-party developers. For them to allow login for users of my system I will use the implicit flow. Also, I plan for those developer accounts to have restricted API access (for example, the number of calls to the API will be limited by plan). What prevents those developers from asking for the username and password of their account on my system on their website, getting the response from my servers with the access token and refresh token, and using my API however they want, without restrictions, and having access to the entire user profile?
Lets say I'm sticking to the resource owner flow, receiving back from the server a token and a refresh token. What should I store on the mobile device and how? What should be stored in the browser and how? the refresh token? and each time he opens the app get a new updated token with that refresh token?
Edit
Just to clarify, because I find a lot of lectures and articles that explain the process from an API consumer point of view (ie. the third-party developer): I am the API owner and the auth server owner, I'm the owner of the user accounts (they are my users of my services), I'm also my own consumer (though the website and the mobile app), and in the future I want to enable third-party developers to allow my users to login with their accounts of my service (kinda like Facebook or Google)
You're correct that you shouldn't store the client_secret in your app, but I doubt you will get around storing the client_id. You could disable the consent screen for your app as well, and build a native login view. You need to store the access_token and the refresh_token on the device (maybe encrypted in a database) if you don't want the user to login everytime they use your app.
As for problem 4, you could do the following:
Embed the client_secret in your (web) app
Set up which hosts have access to your api on the IdentityServer
The IdentityServer generates a salt and sends it to the client
The client calculates a session_secret using hash(ip_address + session_salt)
The client uses the session_secret and the client_secret for the API call
Server validates the hash and client_secret
It's nearly impossible to completely prevent someone from using your API. But you should add various rate limiting methods, such as limiting IP addresses, API calls etc. But nothing will stop someone decompiling your app and accessing your client_id.

Is OAuth 2.0 redundant/unnecessary if the client is the same as the resource owner?

In section 1.1 of RFC 6749, there are four roles: resource owner, resource server, client, and authorization server.
Does OAuth become redundant or unnecessary if the client and the resource owner are the same entity?
For example, I have a closed API and a front-facing web server. (The front-facing web server would be both the client and the resource owner.) I am trying to decide whether to switch to OAuth 2 authentication instead of using the current username/password authentication method. Is there any added security for moving to OAuth 2 if the API remains closed to third-party applications? (That is, no third-parties will ever have access to the API.)
Thanks!
In the case where the Resource Owner and Client/Resource Server roles coincide OAuth 2.0 may become less relevant from a security point of view, since one of the primary objectives of OAuth not to expose primary credentials of the user to the client becomes moot. That is also the reason why the so-called Resource Owner Password Credentials grant is considered to be a legacy/deprecated flow.
However, it may still make sense to follow the OAuth 2.0 pattern for a number of reasons:
the ability to leverage a standardized protocol through stock libraries and
frameworks without relying on custom code
the fact that in your case the Resource Server is still made strictly OAuth 2.0 compliant, dealing with Clients presenting access tokens, irrespective of what the Client/Resource Owner relationship/implementation is; this would make it easier to allow for 3rd-party client access in a future scenario
the fact that you concentrate verification of user credentials on a single path between Client and Authorization Server so each of your Resource Servers don't need to be bothered by checking user credentials individually, possibly dealing with different authentication mechanisms
and perhaps most importantly, also security-wise: once the user has authenticated through the Client using his primary credentials, the Authorization Server can issue a refresh token as well as an access token; the Client can store and use the refresh token to a new access token when the old one expires; this frees the Client from storing the primary user credentials if it wants to keep accessing the API for a long period of time without requiring explicit user interaction and authentication and makes the resulting system less vulnerable for leakage/loss of user credentials since the user credentials (password) are not stored in the Clients
If you have the following issue then you should use OAuth;
Let's say you a Gmail like web mail provider. Some of your users are using a third party app which logs in into your user's account and auto replies certain emails for you. Or you are Facebook like social network web site where some of your users use a third party app which analyzes your friend networks and prints a 2D graph for you. In this case your users are giving away their usernames and passwords. How would they prevent a certain third party app accessing their account after they gave away their username and password? Simply by changing their password. Now you have another problem; other third party apps won't be able to access the user's account. Then the user have to re-give away his password to other apps he trusts. Now this is problem too because it is not user friendly. OAuth is simply a temporary password that your user gives away to a third party app developer. He can revoke it whenever he wants without changing his own password.
Other than that OAuth is unnecessary. Just use a session cookie if you are not going to have third party app developers. It is a random string stored in user side. And on the server side will have whatever you want. Just look how PHP sessions are used and stored on server side. You can define their lifespan and refresh time automatically from php.ini.

Google Drive API username + password authentication

I'm developing an application where Google Drive will be used to manage some documents. The idea is to create a document with some initial template data and provide the users access by adding them as collaborators of the document.
I'm familiar with the OAuth authentication process, I used it in another part of the system to manage the users Calendar...
But in this case these documents will be stored in a generic account of the company, so I can't have the approval prompt for authentication, since users won't have the password of the account.
I'd like to directly authenticate in this account, could be with the username and password hardcoded in the Java code.
Problem that this method of authentication was depreacated and I didn't found a relpacement.
Any ideas?
Thanks in advance,
Phillip
There are 2 ways that comes to mind:
Service accounts: best suited for server side OAuth with traditional backend
Regular Account owned by the application : similar to the process already in place for client side Oauth that you are already familiar with; Auth, store the refresh, ask new token if the AuthCode is expired, and so on.
I personally use and prefer the second solution more as I feel is more flexible to adapt in the future for Oauth Client Side get the tokens and use them server side.

Dilemma with TripIt integration

We are trying to integrate TripIt with our web application for itinerary management. I created a new App and got api key & secret. But we want to use the employee's trip it account and retrieve their trips & create trip in their account. Now i have one dilemma, since i am using my api key & secret, i can able to retrieve trips created in my account, but i want to retrieve trips of whoever logged in with their tripit account, with my api key.
So in this scenario, i will ask for user's trip it credentials and is there a way i can get their trips using my api key? Any viable solution is welcome. If you clear me with the flow i can able to understand.
The (OAuth) API key and secret are issued for your application, not for your specific user account. What this means is that your application can be given permission to access the user's data. If you've ever worked with the Twitter or Facebook APIs, TripIt's API behaves much the same.
You register an application through TripIt (sounds like you've already got this step down)
Using an SDK of your choice, you create endpoints in your code to handle the various steps in the OAuth workflow.
Here is a quick rundown of the workflow for OAuth 1.0, which TripIt uses.
The user begins the process of connecting their TripIt account to your application
Your application builds a request token URL and sends the user to TripIt's OAuth dialog, indicating the callback_url
The OAuth dialog (on TripIt's site) prompts the user to accept or decline permissions
If approved, they return to your site (callback_url) with a 'signed' request token as part of the query string
A backend process, typically a simple CURL request, exchanges the request token for an access token to finalize the process
You store the access token associated with the user in your database and use it for future requests against the API
If you happen to be using PHP, here is an open source example application to take a look at. It does not save the token to a database (just keeps it in the session), but you should be able to glean the basic idea from it.