how to force ownerID when sending a note update on workfront - workfront-api

I can successfully create an update on projects but it seems that I cannot overwrite the thread creator by ownerID.
URL sample:
https://workfronturl/attask/api/note?updates={"noteText":"test","noteObjCode":"PROJ","objID"="projectid", "ownerID":"ownerIDxxxxafda"}&method=POST
Can the ownerID be forced to another user?

If I understand correctly, you want to make an update on behalf of a user. We do this all the time as we have a system that translates updates from another system to Workfront. If this does solve your problem, please be sure to write to Workfront and tell them that they need to leave this functionality in the API in the future. I have confirmed with them that this wasn't supposed to work this way.
So, with regards to solving the problem, you need to do the following:
Login as the user who you want to make an update on behalf of. You can do this without having the users password if you have an API key. Just run the login command as you normally would, but instead of passing in a password, send the username and apiKey.
This will return a sessionID. Use the session ID to authenticate when making your update.
If your system is caching credentials, don't forget to log out or all future updates, changes, whatever, will try to use that session ID.
If you are using Python, we built a function into the workfrontapi_plus (only Python3.x) python library to support exactly this called make_update_as_user. As a note, I haven't managed to publish the documentation for this yet, but the doc strings are there and fully filled out with instructions.

Related

Google OAuth Always Showing Consent Screen

I'm building an installed application that will have features requiring the Google Drive REST API using Qt and C++. I understand Qt is now releasing new libraries to support OAuth flows but let's assume I'm a student and learning to use OAuth at this layer is a requirement for this project.
In my application, I have a working OAuth flow for installed applications that ends with an Access Token and Refresh Token being stored using QSettings (I'm open to input on whether this is a disastrously bad idea too). The application requires no authentication/login for its own sake/data, but it does need authentication to Google for calling API's using an Access Token. This application has no associated web backend being hosted; its simple and should be deployable completely locally (I've written and included a simple TCP server that will receive the authorization redirect_uri and will run and close when called from within the application).
As such, I'm curious about the best way to make sure that, when a user opens my application and wants to use the Google Drive features, they are appropriately authenticated on Google's end. Say, if I maintain an access token in the registry, and this access token is granted per-user/per-application basis (right?), then how can I make sure only the user the token belongs to is able to make calls to the API with it?
Here's my understanding and approach; feel free to correct me or educate me if I've got the wrong interpretation.
If an Access Token is found, perform the following:
Open a browser page to a Google login domain and have the user authenticate there (this could prohibit a user from being able to use a cached login session that would have access to a token they otherwise shouldn't have access to)
If user has correctly authenticated with a Google account, return control to the application and make a test call to an API using the stored token.
If the call fails (responds with an invalid_credentials) I should be able to be sure its because the access token has expired and the application will go through the flow to renew an Access Token from a Refresh Token.
If no Access Token is initially found:
Start a normal OAuth installed application flow
Get the tokens and store them so that when the user opens the application next time the former procedure is used
My issue then is the first two steps if the Access Token is found. Nominally this could be done by the typical OAuth flow but it appears that when using a localhost as the redirect uri, Google will always prompt for consent, regardless of settings for prompt and access_type authorization query parameters.
What can be done to accomplish these first two steps in a way that my application can control (i.e. not a solution that relies on a backend server being hosted somewhere)?
If this question is too open-ended for SO requirements I can make some more restrictions/assumptions to limit the problem domain but I'd rather not do that yet in case I unknowingly rope off a good viable solution.
Thanks for reading! Sorry if its a verbose; I wanted to ensure my problem domain was fully fleshed out!
If you are using an installed application, I wouldn't recommend using or storing refresh tokens. Storing refresh tokens on the client side means that if an intruder gains access to the client's application, they have infinite access to the user's application without ever having to enter the user's credentials. If you do insist on having a refresh token, ensure you follow the Google's installed app flow, with the code_verifier parameter included in your requests.
If the access token is found, you should try to verify it, and if verified then use it at the google api, otherwise force the user to login again (or refresh it if you chose to still use refresh tokens).
If no access token is found, your flow sounds fine.
A few notes on loggin in with Google:
Google will only return a refresh token if you specify access_type=offline in your auth request.
Google will only return a refresh token on the user's first authorization request, unless you always specify prompt=consent in your query params.
In my experience, when leaving out the prompt query param, the user is not prompted for their consent again. If they are logged in to google, you will get a new access token, but no refresh token, unless you have prompt=consent.
I think the idea is you use prompt=consent if you have no record of the user ever using your application. Otherwise if they have used it before, you may prefer to use prompt=select_account to allow the user to select which account he wants to use in case he has more then one, or you can just use prompt=none.
This is just my understanding of it all.
My approach I ended up using was just to deploy with an SQLite db that will be stored in the AppData roaming directory. The db schema includes a field for the user's Name (from the OpenID IDToken field if it exists), the user's picture URL (again from IDToken if it exists), the refresh and access token strings (will be stored as encrypted strings when I get around to it), the user's UID/sub string, and a field for a user name and password.
These latter two fields are authentication fields for within my own application, which, again, I wanted to avoid but it seems impossible to do so. So the user will be prompted to enter a username and password into a form, and these credentials will be checked against the existing SQLite db file mentioned previously.
If they exist and are correct, the user gets logged in and will have access to their respective access and refresh token.
If the user has forgotten their password, they'll be asked for reconsent (going through the installed app flow again), and whatever password they provided during initial login will be used as the reset password. It is considered, for my purposes, that logging into Google for the installed app flow is proof enough that the user account belongs to them and they should have authorization to reset the password.
If the user is a new user and doesn't have a record in the local SQLite db file, then they can also click a button to "Create New Account" - which effectively goes through the authorization flow as well but this time a whole new record is posted to the SQLite db with the appropriate fields filled.
There's still more optimization that could be done but at least I am getting closer to the level of security and control of access to Google user accounts that I want.
I'm not marking this as an answer because I feel like this solution is still not desired and that there should be an easier way. So if someone has evidence or experience of providing an equivalent level of authentication control without needing to maintain a local user account database then I would be more than happy to mark such a method as the solution!
Thanks again!

Meteor: Need simple approach for admin CRM

I'm trying to come up with a way to secure a set of Admin CRM pages that control a Meteor application I'm working on. There's just one codebase, with the server, customer facing website and admin facing website in one project.
I need a login page which can verify one username and password pair, and a simple way to check the status of the user on both the client and server side. I also need a way of the admin's authorization timing out if it hasn't been used for x minutes.
I've looked at the meteor accounts package and it's just way too much fluff for what I need. This website will only ever have one admin user, so there will only be one set of admin username and password to store. I don't want it stored in the database, rather loaded with a settings file on the server on application start. It doesn't need roles, emails, password reset functionality.
Any recommendations for a package or approach I could use to implement this?
I know you said that the accounts:password package seemed a little "overkill", but in reality it really isn't. What you are gaining there is pluggable UI (via accounts-ui and other packages that build off it). The approach I have taken is this (which happens to work well even for apps that do support multiple users, since ultimately you still need to bootstrap your start users).
First, I use a combination of accounts:password and alanning:roles. If you absolutely don't need the roles portion, you could probably get away without it, but in all my personal cases I have found it useful to have multiple levels of ACLs for the various users. We could get into a whole philosophical discussion on using roles/groups to lock down individual features, but that's sort of off topic for this discussion.
Next you need to boot-strap the user(s). Somewhere in your /server folder you will do something like:
if (Meteor.users.find({}).count() == 0) {
// No users created...create default users
Accounts.createUser({
username: 'myuser',
email: 'myuser#mydomain.com',
password: 'myp4ssw0rd!',
profile: { profileProp: 'propVal` }
});
// Add new user to whatever roles needed
}
There are some more things I usually do here, like checking to see if my roles exist, and if not, create them before I try to handle the users, but the key here is to do that when the server starts up.
Once you have your user(s) and role(s) created, it's a matter of checking/verifying the user/roles in your app. For menu items you can show/hide stuff based on whether the user is logged in and/or has a certain role, and you should also verify in your application routes that require ACLs, like your admin route. In addition, use the user id in all your publications as well to limit the data your users can see. Don't rely solely on hiding a menu option...security through obscurity just doesn't work.
Why do I suggest doing it this way? First off, it's really not THAT much code. You could literally do this in probably 20 lines, max, and have a full authentication setup. And the benefit of those lines of code greatly outweigh the 30min tops it would take you, as you will now have "real" user authentication in your app and have the ability to do things like OAuth if you ever decide to in the future. Most importantly, you unlock pre-build UI plugins that you don't have to code, built-in and add-on methods to help check ACLs, the ability to lock down data by user, and you don't have to try to implement your own solution.

symfony web-service with username and password

I will not post any of my code, because this is more just a question to know if it's possible.
I've been googling a lot, but didn't find any concrete solutions. I hope someone can help me here.
The facts:
I have a login form
I need to authenticate the credentials over a web-service
I need to send both username and password, to get back a token if logged in successfully.
The problems:
With a custom provider I'm always stuck with the fact that they only have direct access to the userename, like: loadUserByUsername. I need to access the password there as well, to be able to send this to my web-service.
I have only 1 web-service which sends only back a token if provided username and password are correct.
Question:
How can I access and send both username and password to my web-service?
Thanks!
Generally speaking one would authenticate using an API token to a web service.
That API token is usually issued via an auto-generation script when the user account is created (either by an admin or by a registration form). This token is then passed by the API call to the web-service in a header which then uses it to authenticate the user.
As far as Symfony goes, by far the easiest way of doing this is with Guard. A new component built by Ryan Weaver from KNP.
KNPUniversity has a great tutorial on it (for free).
Note that this is only one option of many, and the 'best' way is probably mainly opinion based and directly related to the use case in question. But it might help you get on the right track.
If the token you want to create should be a JSON Web Token (JWT), a very conventient bundle is LexikJWTAuthenticationBundle, which does almost all of the work automatically. If you just follow the documentation, you will have it quickly up and running. You can combine it with FOSUserBundle, with a custom User entity or whatever.

Meteor / accounts-google: Where is the client secret stored? Is it safe?

After adding packages accounts-google and accounts-ui, and adding {{> loginButtons}} to my meteor app's html, I'm presented with the following button:
This allows me to enter my client id + secret - fantastic!
Where are these stored?
If I'm able to set them without having to login or somehow prove that I'm the owner of the app, does this mean that anybody could set them to something new, by making the same request to my server?
Thanks
Once you set the configuration keys, it won't ask you/your user to enter these credentials again. These secrets are stored in your database, to be specific it is stored in this collectionmeteor_accounts_loginServiceConfiguration. And yes when you're adding the accounts-ui package, all things including securities are done by that package as this package is maintained by mdg(meteor development group). So you can be sure that no one can make request to change/update your credentials.

Correct way of updating user claims on client side

Currently I'm working on project, where we have implemented oauth over asp.net identity using jwt tokens. So far, everything is good and seems right, but recently we have run to a problem. It's more architectural than technical. I tried to search for best practices, could not find anything valuable, so maybe you can help.
Now the problem: Imagine, you have jwt (or any other) token, that contains some claims that can be used on client side. Next step is that user updates some information, which is represented as claim in token (for example phone number).
Question: what is correct way, to reflect this changes in token? First thing, that comes to mind is refresh token, so as soon as user updates some sensitive data, request refresh token and it will contain updated information. But what if I don't use refresh tokens? Than I have to wait for the moment, when user is logged out and than, after next login, issue new token with updated claims.
Other option is to log out user and force him to log in again, but I don't really thing that this is good idea from user experience perspective
Third thing is to get rid of claims and store this information in local storage or somewhere else and automatically update it on phone number update. But in this case, it means that I have to abandon claims, what I also don't like.
Can someone point to correct solution of this problem?
Thanks
Going for refresh token will be best practice to do in this scenario because user should not be prompted by this process and all the things will get completed in the background.
For in-depth analysis you can see this.

Resources