How to get token via API from IBM App ID backed by SAML? - ibm-cloud

I'm trying to use App ID to do user authentication/authorization against a service running in Kubernetes from a CLI tool.
I've provisioned App ID and configured SAML identity provider. I added an application and got the tenant id, client id, and client secret. I also added the appid-auth annotation to the Kubernetes ingress definition.
According to the documentation here https://cloud.ibm.com/docs/services/appid?topic=appid-obtain-tokens, it should be pretty strait forward via curl, but I'm getting Error - cloud directory is OFF.
Here's an example with the credentials X'd out.
$ curl -iX POST \
> https://us-south.appid.cloud.ibm.com/oauth/v4/XXXX/token \
> -H 'Authorization: Basic XXXXXXXXX' \
> -H 'Content-Type: application/json' \
> -H 'Accept: application/json' \
> -d '{"grant_type":"password","username":"testuser#ibm.com","password":"testuser"}'
HTTP/2 403
date: Tue, 04 Jun 2019 17:20:54 GMT
content-type: text/html; charset=utf-8
set-cookie: __cfduid=d8fb55f6b30555b81f64b3c3e40bbf8f71559668853; expires=Wed, 03-Jun-20 17:20:53 GMT; path=/; domain=.us-south.appid.cloud.ibm.com; HttpOnly
x-dns-prefetch-control: off
x-frame-options: SAMEORIGIN
strict-transport-security: max-age=15552000; includeSubDomains
x-download-options: noopen
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
surrogate-control: no-store
cache-control: no-store, no-cache, must-revalidate, proxy-revalidate
pragma: no-cache
expires: 0
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
server: cloudflare
cf-ray: 4e1b948028aec1cf-IAD
Error - cloud directory is OFF
If I use "grant_type":"client_credentials", it returns get an access token, but I need an identity token so the application can do authorization based on the user.
I've tried using the 'web' version in the ingress definition, and the web redirect works fine. So I know SAML is configured correctly.

You're mixing few different concepts here.
SAML authentication works by presenting a Login UI to user. User needs to fill email/password (or whatever credentials are) and then be taken back to the application. Bottom line here is SAML authentication workflow implies human user that can interact with browser in order to enter credentials. In order to achieve SAML federation through OpenID Connect (the protocol App ID is based on), a grant_type called authorization_code is used. This workflow also implies presenting user with login UI. Since SAML authentication cannot be used without presenting user with a UI you cannot use API only approach in order to authenticate users. With SAML you have to use grant_type=authorization_code, which will only work properly in browsers (unless you do html scraping, which is not recommended).
"grant_type=client_credentials" works differently. It is designed for non-user-interactive scenarios, where you do not have human users involved. SAML is used for authenticating users, client_credentials is used for authenticating applications/services.
Check out the Technologies Under the Hood video in App ID Tutorials on youtube, it explains the differences between various workflows - https://www.youtube.com/playlist?list=PLbAYXkuqwrX2WLQqR0LUtjT77d4hisvfK

Related

Connect with PayPal - invalid_client Client Authentication failed with sandbox

I am implementing Connect With PayPal on my vuejs application following this documentation, but I keep getting an invalid_client error when I try to get the access token.
I have created the sandbox REST app on my account and I've enabled "Connect With PayPal". I have also set my return url in the app settings. To build the button I used the button builder and specified my client id, return url and set auth end point as "sandbox". I have added the external script in my index.html and the paypal.use() method in my component.
So now I have the connect button on my interface and when I click on it I am redirected to https://www.sandbox.paypal.com/connect/ which is normal. I can login with my two default sandbox accounts, then I am redirected to the return url that I specified in my app settings, with two url parameters : "code" and "scope" as described in the documentation.
However I am stuck at this step where I need to get an access token for the connected user.
I have tried to run this curl request with my client id / secret and the code from the url but as I said before it doesn't work and I am getting this error everytime :
HTTP/1.1 401 Unauthorized
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
Content-Length: 77
Content-Type: application/json
Date: Wed, 08 Jul 2020 22:01:03 GMT
Paypal-Debug-Id: 8abaa5940b688
X-Paypal-Token-Service: IAAS
{
"error":"invalid_client",
"error_description":"Client Authentication failed"
}
I have checked my client id and secret multiple times and I can't understand why this is not working, does anyone have an idea ?
Solution for this type of error is to verify and validate everything is being sent correctly in the request, and properly encoded
curl's -u flag makes username:password header authentication easier
curl's -v flag will give visibility about the actual communication, to validate

TFS Web Calling an external REST Service throws 401 error

When creating a web hook within TFS (to access an external rest service url), I get a 401 error when testing (within the TFS application). I think call is not hitting API at all.
Below is the response I can see
Status Code: 401
Reason Phrase: Unauthorized
HTTP Version: 1.1
Headers:
{
Server: Microsoft-IIS/7.5
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
X-UA-Compatible: IE=EmulateIE8
Date: Fri, 30 Mar 2018 21:05:26 GMT
Content-Length: 1293
Content-Type: text/html
}
Any help would be appreciated!
The error ID 401 usually related to the authorization.
You could first use postman to double check user ID access to the API.
Also use week hook to access some other rest service url such as the example in Web Hooks. This will narrow down if the issue related to rest service url.
Besides try to use Basic Authentication, you can use alternate account instead. How to please take a look at:Protecting a VSTS Web Hook with Basic Authentication

ServiceAccout has empty calendarList after sharing a calendar has been shaired with it

On creating a new service account via Google Console, when then sharing a calendar with the service account, the calendar doesn't appear in the calendarList response for the authenticated service account.
This was working okay for some time but appears to have started failing more recently.
Oddly, if I delete the shared account entry on the calendar and then add it back in, it usually works. It doesn't appear to be a time delay as have waited hours initially and always zero results in the calendar list, until removing the shared account on the calendar and resharing.
The following are steps I've used to reproduce:
In Google Console web UI, create a new service account with 'Furnish a new private key' selected to download the JSON key.
In the Google Calendar web UI, go to calendar settings and 'Share this calendar', then share the calendar with the service account email, then save the changes.
In REST calls, authenticate with the JSON key with POST call to oauth2/v3/token
Send GET request for calendar/v3/users/me/calendarList
then optionally to show it working...
Delete the service account share from the calendar and save.
Add the service account email to the calendar share and save.
Repeat steps 2 and 3. This time it will probably work.
This is partially a manual process for our end users to create a service account and share calendars via Google web UI. Note I've been using additional calendars on my own Google account to share with the service account (this reflects our end user use case), rather than just the default calendar.
Client code is REST based. To provide an example I have shown the REST requests and responses below. There are simply two requests, one to authenticate and one to fetch the calendarList. These occur after the manual steps in the UI to create a service account and then share a calendar with that account.
---
Request:
POST https://www.googleapis.com/oauth2/v3/token HTTP/1.1
Accept: application/json, application/xml, text/json, text/x-json, text/javascript, text/xml
User-Agent: RestSharp/105.2.3.0
Content-Type: application/x-www-form-urlencoded
Host: www.googleapis.com
Content-Length: 758
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=[ASSERTION_JWT_HERE]
Response:
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: Mon, 01 Jan 1990 00:00:00 GMT
Date: Tue, 14 Mar 2017 20:17:18 GMT
Vary: Origin
Vary: X-Origin
Content-Type: application/json; charset=UTF-8
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Alt-Svc: quic=":443"; ma=2592000; v="36,35,34"
Content-Length: 197
{
"access_token": "ya29.ElkOBAzSOzE_J2VOGFeWnTAGXdtoadW2FbnGga99SrMeamL7j6KetKomvT4aoy4jsRCcXpK-N6sxRBLFUaj_kPWFin4m6xvg_CtaTtkG5tVc_IxS7IezJDf32g",
"token_type": "Bearer",
"expires_in": 3600
}
---
---
Request
GET https://www.googleapis.com/calendar/v3/users/me/calendarList?minAccessRole=reader HTTP/1.1
Authorization: Bearer ya29.ElkOBAzSOzE_J2VOGFeWnTAGXdtoadW2FbnGga99SrMeamL7j6KetKomvT4aoy4jsRCcXpK-N6sxRBLFUaj_kPWFin4m6xvg_CtaTtkG5tVc_IxS7IezJDf32g
Accept: application/json, application/xml, text/json, text/x-json, text/javascript, text/xml
User-Agent: RestSharp/105.2.3.0
Host: www.googleapis.com
Accept-Encoding: gzip, deflate
Response:
HTTP/1.1 200 OK
Expires: Tue, 14 Mar 2017 20:17:19 GMT
Date: Tue, 14 Mar 2017 20:17:19 GMT
Cache-Control: private, max-age=0, must-revalidate, no-transform
Vary: Origin
Vary: X-Origin
Content-Type: application/json; charset=UTF-8
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Content-Length: 202
Server: GSE
Alt-Svc: quic=":443"; ma=2592000; v="36,35,34"
{
"kind": "calendar#calendarList",
"etag": "\"p328bl14pt3bd40g\"",
"nextSyncToken": "CJC6hJno1tICEj10ZXN0MS05MjhAY2FsZW5kYXItY29ubmVjdG9yLS0tb25lbGFuLmlhbS5nc2VydmljZWFjY291bnQuY29t",
"items": []
}
---
Note, I haven't provided the actual JWT for the ouath request, but the authentication is working fine. Also note the calendar is shared as either read or modify with the service account. I can also query the calendar itself and fetch events using the service account, but it is querying the list of calendars associated with the account that fails.
Had also raised this as an issue here but posting this here also in case I'm missing something, although as said all this was working fine until more recently, and our existing unchanged client software has started failing with newly created service accounts.
When you share a calendar with someone VIA the google calendar website the code on the website automatically adds the calendar to the users calendar.list. All the calendarlist is the list on the bottom left of the google calendar website. A user can have access to a calendar without it being in their calendarlist.
When sharing a calendar wish a service account this does not always happen. None of the service accounts I have shared my calendars with have ever had anything in their calendarlist. If you need it to be in the calendarlist then you should have the service account insert it. Using CalendarList: insert just grab the calendar id in question off of the website.

Azure REST API : oAuth2 authentication granted but invalid token on request

I have a question about authenticating to azure mobile management API, to send push informations to the API.
I well manage to authentify and receive a token bearer matching to the provided data (tenant id, client id, client secret...), but when I try to create a campaign, I receive the following response :
[2016-10-25 11:45:51] (::1) fail to send send request https://management.azure.com/subscriptions/fb8226dc-194f-4562-9dc9-c72f56bd728a/resourcegroups/MobileEngagement/providers/Microsoft.MobileEngagement/appcollections/XX-Collection/apps/XX-TEST-android/campaigns/announcements?api-version=2014-12-01
with {"name":"The Evian Championship 20... - 25/10/2016
11:45:50","type":"only_notif","deliveryTime":"any","pushMode":"one-shot","notificationTickerIcon":true,"notificationIcon":true,"notificationCloseable":true,"notificationSound":true,"notificationVibrate":false,"notificationTitle":"Soci\u00e9t\u00e9
G\u00e9n\u00e9rale","notificationMessage":"The Evian Championship
2016","actionUrl":"://webviews/main/build/events.html","notificationType":"system"}
| "HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
x-ms-failure-cause: gateway
x-ms-request-id: 40e30675-2144-452a-9ab9-632a393d8783
x-ms-correlation-request-id: 40e30675-2144-452a-9ab9-632a393d8783
x-ms-routing-request-id: WESTEUROPE:20161025T094550Z:40e30675-2144-452a-9ab9-632a393d8783
Strict-Transport-Security: max-age=31536000; includeSubDomains
Date: Tue, 25 Oct 2016 09:45:49 GMT
Connection: close
Content-Length: 281
{"error":{"code":"InvalidAuthenticationToken","message":"The received access token is not valid: at least one of the claims 'puid'
or 'altsecid' or 'oid' should be present. If you are accessing as
application please make sure service principal is properly created in
the tenant."}}" was returned
Here's the request :
POST
/subscriptions/fb8226dc-194f-4562-9dc9-c72f56bd728a/resourcegroups/MobileEngagement/providers/Microsoft.MobileEngagement/appcollections/XX-Collection/apps/XX-TEST-android/campaigns/announcements?api-version=2014-12-01
HTTP/1.1 Host: management.azure.com Authorization: bearer
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ikk2b0J3NFZ6QkhPcWxlR3JWMkFKZEE1RW1YYyIsImtpZCI6Ikk2b0J3NFZ6QkhPcWxlR3JWMkFKZEE1RW1YYyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuYXp1cmUuY29tLyIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzRmNGFkYjA3LWU5OWQtNDg5NC04OGZjLTZkYzc4ODAzNDI3Zi8iLCJpYXQiOjE0NzczOTUxNzEsIm5iZiI6MTQ3NzM5NTE3MSwiZXhwIjoxNDc3Mzk5MDcxLCJhcHBpZCI6IjUzNzMyOTAwLTU2NGMtNGI2OS1hNGRhLTU0OTQ0ODVkYTFhNiIsImFwcGlkYWNyIjoiMSIsImlkcCI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzRmNGFkYjA3LWU5OWQtNDg5NC04OGZjLTZkYzc4ODAzNDI3Zi8iLCJ0aWQiOiI0ZjRhZGIwNy1lOTlkLTQ4OTQtODhmYy02ZGM3ODgwMzQyN2YiLCJ2ZXIiOiIxLjAifQ.WvWXETt9IFy_eX2Q8LlguTec9KA2TLgILUs10QULNMYgf1sHUpXdnRhDBqq5Foo_gwF_u2zl1NNYRLmdN3Q0IR3LPspiutAhC_KXvGXmJH2TtxTi9U2bt1Zvf5BsafHkxDdlDG6vymu-3O4cK9HQMu7l0XtPqzcEHcQny94xAq66_TSNa3FhZclwEBnaTI81B5g9NzvET10C0j8ZW0OsRNzc0-czS8RqtXulp1rkIEQc7VhTTDx9feSPi3BJlyhiKxUzfnEn8xUkfqlUEQuqyerqUoRIlbFvhhOT7Gjo6_WJN21Wn-23gcEchaRETWzYh-nTJSeKFzwA-mROOdmUzw
User-Agent: Guzzle/5.3.1 curl/7.50.0 PHP/5.6.25 Content-Length: 455
(note : I changed some characters in this displayed bearer by security reasons)
The (real) bearer was obtained requesting https://login.microsoftonline.com/{TENANT_ID}/oauth2/token, using this body :
grant_type=client_credentials&client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&resource=https://management.azure.com/
Would you have an idea about the reason why the API returned this message ?
Thanks a lot !
The received access token is not valid: at least one of the claims 'puid' or 'altsecid' or 'oid' should be present. If you are accessing as application please make sure service principal is properly created in the tenant
It seems that your access token is not valid. I would suggest you follow with this article to get a new token then try again.

How to login to RQM using REST API?

I'm trying to communicate with IBM Rational Quality Manager server using its REST API. I'm using RESTClient browser plugin, and while the browser is logged in, everything works as expected. For the record, my requests look like
https://server/qm/service/com.ibm.rqm.integration.service.IIntegrationService/resources/project/testscript/urn:com.ibm.rqm:testscript:42
However, if I wait long enough for RQM to logout, REST API says I need to login back to proceed (see below). I'm pretty sure this is possible to do via the API itself, because RQM ships with RQMUrlUtility which accepts username and password and runs basically the same REST requests I'm using:
java -jar RQMUrlUtility.jar -command GET -user JazzUserID -password JazzPassword -filepath pathtoFile -url REST_URL
So far, I have found this topic explaining how to login using HTTP basic authentication. Following this advice, I have added Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ= (not my real password) to the request, but RQM still fails to login. I have also tried setting User-Agent to a bogus value, as well as sending the value from JSESSIONID in X-Jazz-CSRF-Prevent header as described here, but regardless of all these headers being present or not, I get the same response:
Status Code: 200 OK
Cache-Control: no-cache="set-cookie, set-cookie2"
Connection: Keep-Alive
Content-Encoding: gzip
Content-Language: en-US
Content-Type: text/html; charset=UTF-8
Date: Tue, 26 Jan 2016 15:48:02 GMT
Expires: Thu, 01 Dec 1994 16:00:00 GMT
Keep-Alive: timeout=10, max=100
Set-Cookie: JazzFormAuth=Form; Path=/qm; Secure
x-com-ibm-team-scenario=ac55f959-c738-4ef0-854d-6e37648edcba%3Bname%3DInitial+Page+Load%3Bextras%3D%2Fqm%2Fauth%2Fauthrequired%2C1453823282026; Path=/
Transfer-Encoding: chunked
X-Powered-By: Servlet/3.0
X-com-ibm-team-repository-web-auth-msg: authrequired
Can anyone with experience with RQM API tell me what's wrong? Or perhaps I'm missing something basic, common to most RESP APIs out there?
Could it be your header name?
Authorisation: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Should probably be:
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Notice the "z".