Authentication not working with VersionOne REST API - rest

Ok, I have a technical question here. We've developed an integration component in XStudio so that we can pick VersionOne's "Stories" (as "Requirements" in XStudio) and "Defects" (as "Bugs" in XStudio). This way you can execute your tests and manage the results, metrics etc. from XStudio but also manage the complete traceability matrix (Products -> Requirements -> Tests -> Test campaigns -> Bugs) in XStudio using VersionOne's items. We handle the links our side.
To do this, we implemented the connector using VersionOne's REST API.
Everything works great! very fast etc.
We tested it using a free server from VersionOne with no problem. Our Java code manage cookies so that it authenticates using "Basic Authentication" protocol, we retrieve the cookie from VersionOne, store it in the local CookieStore and provide that cookie in the next requests so that we do not have to authenticate again and again. All this worked fine from our side.
The content looks like this:
{X-Instart-Request-ID=[7405870175418545839:SEN01-NPPRY09:1396448658:44],
null=[HTTP/1.1 200 OK],
Date=[Wed, 02 Apr 2014 14:24:17 GMT],
Content-Length=[16063],
Expires=[-1],
VersionOne=[Ultimate/14.0.7.6706; Scrum],
Set-Cookie=[.V1.Ticket.ncnuaaa=HFZlcnNpb25PbmUuV2ViLkF1dGhlbnRpY2F0b3LqgwAAB1hTdHVkaW+CjqLWdBzRCP8/N/R1KMorEByFu31RuGY+eqVCi1FHvTE=; path=/; HttpOnly],
Connection=[keep-alive],
Content-Type=[text/xml; charset=utf-8],
Server=[Microsoft-IIS/8.0],
Pragma=[no-cache],
Cache-Control=[no-cache]}
BUT... when we run our code on our client's environment, we don't get the original cookie for any reason !?
{cache-control=[no-cache],
content-type=[text/xml; charset=utf-8],
null=[HTTP/1.1 200 OK], expires=[-1],
content-length=[16063],
server=[Microsoft-IIS/8.0],
date=[Wed, 02 Apr 2014 12:34:08 GMT],
pragma=[no-cache]}
When our code get the header fields from the connection and we try to get the "Set-Cookie" field it can't find it and a popup is automatically display.
Map<String, List<String>> headerFields = connection.getHeaderFields();
List<String> cookiesHeader = headerFields.get("Set-Cookie");
The popup is asking to authenticate (by the way on "www6.v1host.com/192.33.31.50" while it was more expected "www6.v1host.com/abcded" - maybe ther's a clue here?).
If we authenticate on your server here everything continues normally and everything works ok.
But we shouldn't have to authenticate again as we do it in the connection before:
String plainAuth = username + ":" + password;
encodedAuth = ("Basic " + new String(Base64.encode(plainAuth.getBytes()))).replaceAll("\n", "");
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", encodedAuth);
connection.setRequestProperty("Connection", "keep-alive");
So, not sure if this is because the authentication is not working (it would explain why the cookie is not returned and the popup ask the user to explicitly authenticate) or there is something specific in terms of cookie management...
Do you have any idea what could be going on here?
This code is working well on many different other REST APIs using Basic Auth. and Cookies.
Thanks in advance,

It sounds like you work for XQual, the developers of XStudio. If so, please reach out to me. We are always happy to list another integration.
Assuming this is intended to work for more than just 1 customer, I have a couple pieces of advice:
Provide a meaningful user agent header. This helps us be pro-active with your integration. The header is useful even for custom, one-off products, but is even more important when other vendors are involved.
Use OAuth2 for authentication. There are plenty of good libraries for OAuth2 in Java. We have an upcoming blog post where we show how it can be done with Apache Oltu.
To your specific question, I have some hunches:
You might be expecting too much about how VersionOne is deployed. VersionOne is offered both on-premise and on-demand. Your customer may be putting "192.33.31.50" into the configuration to represent on-premise, while you are expecting an instance name for on-demand. Also beware that not all on-demand instances are on "www6".
If on-premise, VersionOne also offers an installation option for Windows Integrated Authentication. In which case, you may not be getting the headers you were expecting. This is one reason I recommended OAuth2 above. OAuth2 is always available for API calls, regardless of the user authentication mechanism.
To better diagnose, could you share some code that shows how you construct the request URL?

Related

LinkedIn API: fetching our company's posts & profile info

So, I'm making this application, and it's required that it has an embed thingy containing the recent LinkedIn posts as well as basic profile info of the company...
Since I like the Law of Minimum effort, the first thing I saw that made my eyes sparkle was the RSS feed... But it seems like it's been phased out. It just redirects to the company page, period.
Then I realized that we have 2 APIs, v1 being superdead since May.
So, I succesfully generated a v2 access token, keeping in mind that it will have to be renewed every 2 months, but hey, nothing's perfect.
Anyway, I know there's a v1 endpoint that would seem to put me on the right track:
https://api.linkedin.com/v1/companies/{id}:
(id,name,ticker,description)?format=json
However, when I go to the v2 docs (https://learn.microsoft.com/en-us/linkedin/shared/authentication/authorization-code-flow?context=linkedin/context), there's this entire, very detailed section about Authentication, and a section titled "API guide" which talks about "API Concepts" as well as "Best Practices"... but no section detailing just where the endpoints are and how to use them?????
Please, help me, SO, how do I get a company's recent posts as well as basic info like name and pfp?
Thank you in advance.
UPDATE: I have made progress, I think.
I found this: https://learn.microsoft.com/en-us/linkedin/marketing/integrations/community-management/shares/company-pages-migration
And this: https://learn.microsoft.com/en-us/linkedin/marketing/integrations/community-management/organizations/organization-lookup-api
I am making the call and after basically having to guess how to input my token (it must be included as the oauth2_access_token parameter) I get a 403 error DESPITE me being an administrator for the organization I'm looking up.
Call: https://api.linkedin.com/v2/organizations/XXXXXXXX?oauth2_access_token=my-token
Response:
{"serviceErrorCode":100,"message":"Not enough permissions to access: GET /organizations/00000000","status":403}
This makes me think maybe I need to request extra permissions on authentication... but THAT I do not find anywhere (i.e. what the permissions are. I only find really vague stuff with NO details. eg: https://learn.microsoft.com/en-us/linkedin/shared/authentication/permissions?context=linkedin/context)
UPDATE 2: As suggested by #ManvinderSingh I removed the oauth2_access_token param and instead included my token in the Authorization header. This works awesome for the /v2/me endpoint, for instance, BUT still 403's me on the v2/organizations/XXXXXXXX endpoint for an organization that I am an admin of.
As per the documentation https://learn.microsoft.com/en-us/linkedin/shared/authentication/authorization-code-flow?context=linkedin/context#step-4-make-authenticated-requests.
You have to send the token in the Authorization header like this.
Authorization: Bearer {access_token}

flask-jwt-extended - Catch raise RevokedTokenError('Token has been revoked')

I already tried reading the documents as well try out the changing default behaviors https://flask-jwt-extended.readthedocs.io/en/latest/changing_default_behavior.html to handle the error (the link shows how to handle expired token) and search around in google everything in every keyword combination i could do but seems no one has example about this.
I tried using #jwt.revoked_token_loader to handle the RevokedTokenError but it seems it doesn't work as I applied it like this
#jwt.revoked_token_loader
def revoked_token_response(revoked_token):
jwtkn = revoked_token['jti']
return jsonsify({
'msg': 'token {} already been revoked!'.format(jwtkn)
)}, 401
actually, i don't know exactly how does the example on the link to handle expired tokens had parameter of 'expired_token', is that self-declaration like what I did above on the 'revoked_token'?? as far as I know, 'jti' is like a default value in the flask-jwt-extended package as I see error whenever I don't use this (in my db, it is different but there is no problem at all.
I tried following this tutorial and it works out fine on my side (as well his original code source) but I see that this one doesn't have a catch exception also on Revoke Tokens https://codeburst.io/jwt-authorization-in-flask-c63c1acf4eeb
I use postman and if based on the tutorial link, here's how i get this
i do login
i use the access token generated to access protected routes ('/secrets')
i do logout
i use again the access token generated to access protected routes
after the last one, i get this error on my server side (ide):
....flask_jwt_extended\utils.py", line 216, in verify_token_not_blacklisted
raise RevokedTokenError('Token has been revoked')
flask_jwt_extended.exceptions.RevokedTokenError: Token has been revoked
127.0.0.1 -- [02/Jul/2019 22:25:26] "GET /secrets HTTP/1.1" 500 -
in postman, this is what I get:
{
'message': 'Internal Server Error'
}
my target is to send out a custom json response instead of 'Internal Server Error'
edit:
I am no wiz on programming or such, a beginner that wanted to practice out python about secured web development. I don't yet quite understand still how decorator works out in terms of application, etc. so i don't know if others tweaks out the flask-jwt-extended package to work such things out.
Getting back a 500 error normally occurs because of a bug in other flask extensions and how that interact with native flask errorhandlers. You can find a bunch of discussions about it here (https://github.com/vimalloc/flask-jwt-extended/issues/86), but the tl;dr version is you might need to set app.config['PROPAGATE_EXCEPTIONS'] = True if using something like Flask-Restul, or use a hack like this if using flask-restplus:
jwt = JWTManager(app)
api = Api()
jwt._set_error_handler_callbacks(api)
If those don't help you, please take a look through that linked github issue, and if nothing in there helps make a reply in that issue detailing your setup.
Cheers.

OneNote on SharePoint REST API

The OneNote team recently published a blog post in which they explain how to access data from OneNote notebooks that are stored on SharePoint ('site-hosted notebooks', as they refer to them).
I'm trying to use the API as they describe it, but I'm unable to get it to work. Specifically, the first step is to find out my site collections and site ID using the following API call:
https://www.onenote.com/api/beta/myorganization/siteCollections/FromUrl(url='{full-path-to-SharePoint-site}')
It seems to fail no matter what I do: I tried to put the full path to my SharePoint site with and without 'http://' or 'https://', tried to write my organization name in various ways (with '-my' at the end, and without it), and probably a few other combinations as well - it just doesn't work. I keep getting error 400 / bad request.
Any help would be greatly appreciated.
So ... I had a fairly long correspondence with the guys from Microsoft, and here's what I learned:
If you're using a browser or a browser plug-in to test some of your REST APIs calls, it's not enough to be logged-in as the relevant user. This works for SharePoint and other Office 365 APIs, but not for this OneNote API. You must send "Authorization: Bearer ... " in the request headers.
Probably my stupid mistake, but 'myorganization' in the URL https://www.onenote.com/api/beta/myorganization/siteCollections/FromUrl(url='{full-path-to-SharePoint-site}') is not the name of your organization / domain: it's the literal string 'myorganization'.
Finally, the 'full-path-to-sharepoint-site' should point to https://xyz.sharepoint.com and not to https://xyz-my.sharepoint.com.
This syntax works like a charm for me:
https://www.onenote.com/api/beta/myorganization/siteCollections/FromUrl(url='https://XYZ.sharepoint.com/sites/ala')

GitHub OAuth in lua

I am working on a library in LUA for an ipad app called Codea. I'm trying to figure out to use OAuth for GitHub Gists. Only part that i can not figure out is how to get an Auth token via code. I used curl in terminal to get myself a token but this seems to be to much work for other users.
I've read through the github api docs multiple times but I cant figure out how to get a Token programmatically. I've tried to duplicate the method I've used to GET and POST gists but it does not seem to work. I'm not sure how to pass the username and password.
I'm creating a table with the needed params then encoding it in json. Everything I try gets a 404 error or 500 error. Thank you all in advance.
local url = "https://api.github.com/authorizations"
local d = {}
d.scopes = {"gist"}
d.note = "AutoGist Codea"
projectAuth = json.encode(d)
opts = { data = projectAuth }
opts.method = "POST"
opts.headers = {Authorization = "basic " .."username:password"}
http.request(url,successCallback,failedCallback,opts)
Scopes are coming, but only in Q4 2013.
See "OAuth changes coming" (October 2013, by Tim Cleam - tclem):
Starting today, we are returning granted scopes as part of the access_token response.
For example, if you are making a POST with the application/json mime-type you’ll see an additional field for the granted scopes.
{
"access_token":"e72e16c7e42f292c6912e7710c838347ae178b4a",
"scope":"repo,gist",
"token_type":"bearer"
}
Right now, these scopes will be identical to what you requested, but we are moving towards a feature set that will allow GitHub users to edit their scopes, effectively granting your application less access than you originally requested.
You should be aware of this possibility and adjust your application behavior accordingly.
Some things to watch out for and keep in mind:
Most third party applications using GitHub OAuth to identify users have the best success in adoption by starting out with a request for the minimum access that the application can possibly get away with.
Something like no scopes or just user:email is very sane.
It is important to handle the error cases where a users chooses to grant you less access than you originally requested.
Now that we are surfacing the granted scopes on the access_token response, applications can warn or otherwise communicate with their users that they will see reduced functionality or be unable to perform some actions.
Applications can always send users back through the flow again to get additional permission, but don’t forget that users can always say no.

Acessing calendar of user email address using Java

I have a requirement. I need to access a user's email that is on company specific domain. I need to get the calendar of that user and publish it to web application. I am exhausted finding any API that can help me to do that. The email client used by company is Thunder Bird, So , in specific, I need to access calender's from Thunder Bird for that particular user. Can any one tell me some suggestions for this.
Kumar
Your question is very unprecise (what kind of is the server providing the emails/calendars? Is there a LDAP Domain? And so on). I suppose you are talking about an old Exchange Server because of some Domain and WebDAV and problems while searching? But I maybe can give you at least a bit of help, that may lead you to already trodden paths of other coders, so that you may find a simple and fast solution.
Today I finished a M$ Exchange 2003 Connector as a proof-of-concept. And I tell you, that it was really hard for me as a student while an Internship. Nonetheless, I researched and searched and queried and annoyed other to get hints for a useful API, but none fulfilled my purposes.
One small framework I found which is nice to use is called Sardine WebDAV Client for Java. The project is very light-weighted, though it was helpful to get an idea how WebDAV works, even due to sources you can always look at.
All other solutions aimed at a lot of different MAPI CC++ Libs for Linux. That was no option for me.
So, what options did I have? No direct access to the customers Exchange 2k3 Server, but one email account. So you all may forgive me, but I found it much easier to make a POST request to the E2k3 Server via OWA, because it was activated than trying some heavy lib supported ways of accessing.
Maybe this comes to your avail- Get the form-field information from the OWA form and build a connection string you Post to the server. Perhaps this is a string that might give you an idea. So you need to call a DLL like this:
HttpPost httpPost = new HttpPost("https://" + getUrl()
+ "/exchweb/bin/auth/owaauth.dll");
httpPost.setEntity(new StringEntity("destination=https%3A%2F%2F"
+ getUrl() + "%2Fexchange%2F&flags=0&username=" + getUser()
+ "&password=" + getPassword()
+ "&SubmitCreds=Log+On&trusted=4&flags=4", "UTF-8"));
The information how to make a form based authentication came from here: Exchange 2003 Forms-Based Authentication. As you can see I grabbed from the browser the Link, which is used to communicate with the E2k. The next step is simple - send the request and wait for...
HttpResponse response = httpclient.execute(httpPost);
If you get a good response in return, then you can filter out the Session ID. The next step after a successful login is to search for appointments. Therefore you should find a appropriate method to work with on an established WebDAV connection by asking M$ for some Information: SEARCH Method
Then, you read what it can do. I went on with a well-known Find-Machine and queried for Searching Calendar Folders with WebDAV.
After that you can create a POST request like this:
HttpPost hp = new HttpPost(
"https://owa.SERVER.de/exchange/USER/Calendar") {
#Override
public String getMethod() {
return "SEARCH";
}
};
Now you can make use of the SEARCH method. That is good, because your program is ready to send the request.
hp.setEntity(new StringEntity(QUERY, ContentType.TEXT_XML));
HttpResponse response = httpclient2.execute(hp);
I know it is no perfect solution. Because there were two circumstances which made me wonder. Firstly: I retrieved a Session ID, but I wasn't in need to re-use it anywhere, as long as I kept it in a field. And secondly: I needed to call for another HttpClient. I cannot explain right now. If I used the same HttpClient I used for logon, then all request were in vain. That is why I had to call another HttpClient.
The last and most difficult step was to get behind the query, because the only debugging help I had were HTTP Error Numbers and the bad descriptions in the MSDN. Sorry for that. Well, this is what really worked fine. I got behind it with Trial and Error.
private final static String QUERY = "<?xml version=\"1.0\"?><g:searchrequest
xmlns:g=\"DAV:\"><g:sql> Select \"DAV:href\", \"urn:schemas:calendar:dtstart\",
\"urn:schemas:calendar:dtend\", \"urn:schemas:mailheader:subject\",
\"urn:schemas:calendar:duration\" FROM Scope('SHALLOW TRAVERSAL OF
\"/exchange/USER/Calendar\"')</g:sql></g:searchrequest>";
This is no particular query. I just alternated it from another Document and removed all stuff I didnt't need.
I hope this helps you a bit. About providing Thunderbird Appointment/Calendar dates I can't tell anything because this is yet beyond my knowledge.
Best regards and good night,
Semo