What is the best approach to logout from keycloak after authentication via pkce? - keycloak

What is the proper way to logout?
These are the keycloak client settings:
Realm: REALM
Client ID: pkce-client
Client Protocol: openid-connect
Access Type: public
Standard Flow Enabled: ON
Valid Redirect URIs: http://localhost:4200/
Backchannel Logou: ON
OpenID Connect Compatibility Modes
Use Refresh Tokens: ON
Advanced Settings:
Proof Key for Code Exchange Code Challenge Method: S256
Is there a good documentation?
My idea was to delete the token on the client side, but then the session is still active in keycloak.
The solution was to call the following URL:
http://localhost:8180/auth/realms/REALM/protocol/openid-connect/logout?id_token_hint=InR5cCIgOiAiSldUIiwia2lkIiA6ICIxUVJwMXAtbmk1WmcyZmlyRHFoRS1iS1hwemZDaWFocGs4Zi1XRkQtRDZ3In0.eyJleHAiOjE2NDE3NjUyNjYsImlhdCI6MTY0MTc2.......

OIDC standard (implemented by Keycloak) supports RP initiated logout. So make browser redirect (not a XMLHttpRequest request only) to end_session_endpoint with proper logout parameters.
BTW: end_session_endpoint is not the same as revocation_endpoint; logout != revocation.
But this is OIDC logout only (logout from the Keycloak). You may have still own app session (it depends on the app implementation), so app needs to destroy app session ("delete refresh token on the client side", ...) to have logout from the app.

You can create a logout service backend that you make available on /logout endpoints of all your services.
When the service is called, it first obtains the ID token for the client used to connect:
curl -k https://<keycloak-host>/auth/realms/<realm>/protocol/openid-connect/token \
-d "grant_type=client_credentials" \
-d "client_id=<client-id>" \
-d "client_secret=<secret>" \
-d "scope=openid"
See this answer.
Then it constructs a redirect URL in a format like this based on host of user:
https://<host>?cache-buster=1445660571
With an optional cache buster.
Create a redirect URL to the authorization server in this format:
https:///auth/realms//protocol/openid-connect/logout?id_token_hint=&post_logout_redirect_uri=<url encoded redirect URL>
Then create a response with status code 303 (See Other) with as Location the URL constructed above, and as headers you set the "kc-access", "kc-state", "OAuth_Token_Request_State" and "request_uri" cookies to expired. Clojure example:
(defn- expired-cookie [host cookie-name]
(str cookie-name "=; "
"domain=." host "; "
"path=/; "
"expires=Thu, 01 Jan 1970 00:00:00 GMT; "
"HttpOnly"))
Example response:
status: 303
headers:
{"Location" "https://<keycloak host>/auth/realms/<realm>/protocol/openid-connect/logout
?id_token_hint=<id token you obtained>
&post_logout_redirect_uri=<url encoded redirect URL>"
"Set-Cookie"
["kc-access=; domain=.https://<domain>; path=/;
expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly"
"kc-state=; domain=.https://<domain>; path=/;
expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly"
"OAuth_Token_Request_State=; domain=.https://<domain>; path=/;
expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly"
"request_uri=; domain=.https://<domain>; path=/;
expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly"]}
This returned response will log the user out and redirect to the constructed redirect URL (for example, where the user came from).
This /logout endpoint can be made available as a route on all services that use Keycloak.

The solution was to call the following URL:
http://localhost:8180/auth/realms/REALM/protocol/openid-connect/logout?id_token_hint=InR5cCIgOiAiSldUIiwia2lkIiA6ICIxUVJwMXAtbmk1WmcyZmlyRHFoRS1iS1hwemZDaWFocGs4Zi1XRkQtRDZ3In0.eyJleHAiOjE2NDE3NjUyNjYsImlhdCI6MTY0MTc2.......

Related

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

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

yii2 REST authentication keeps its authentication information

Iam working on a REST module in Yii2. The client is able to authenticate on the server and is also able to get the requested response. I have seen, that the client authenticates one time to the system. It seems that the client stores its authentication information, because no further authentication for following requests is needed.
Of course, Iam interested that each REST request needs an authentication. I have seen, that there could be one way to do some fixed settings in the configuration of the app, which I would like to avoid.
I guess that the authentication information is stored in a cookie. I assume that the cookie is named'_csrf-frontend'. Now I try to remove this cookie within a controller function.
$cookies = \Yii::$app->response->cookies;
$cookies->remove('_csrf-frontend');
unset($cookies['_csrf-frontend']);
I've added additionaly recommended settings of Idgs answer, but still no luck. After a refresh of the page the authentication information must be kept, because still no authentication is necessary.
A look in the Headers shows:
Response Header:
Cache-Control no-store, no-cache, must-revalidate
Connection Keep-Alive
Content-Type application/json; charset=UTF-8
Date Thu, 29 Mar 2018 06:36:37 GMT
Expires Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive timeout=5, max=100
Pragma no-cache
Server Apache/2.4.18 (Ubuntu)
Set-Cookie _csrf-frontend=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; HttpOnly _identity-frontend=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; HttpOnly
Transfer-Encoding chunked
Request Header:
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language de,en-US;q=0.7,en;q=0.3
Authorization Basic ZG9yaXMua3JhdXNAdmVydHJlbmQuY29tOktyYXVzMTAwMA==
Connection keep-alive
Cookie eafab809c11b0a847c07e9c4f2b93936=uv3f1tof6la24616p7bkf59p55; advanced-frontend=mobbni6v6492kde73amtdvcqi3; _csrf-frontend=4d2ddb54290d2fa7fcc9c4a9900726b795e83aadc658fc0f50395bf7ded0c86aa%3A2%3A%7Bi%3A0%3Bs%3A14%3A%22_csrf-frontend%22%3Bi%3A1%3Bs%3A32%3A%22Oiy_JOiLMg_X0Hz666f0OWpG_r-jcvnO%22%3B%7D
DNT 1
Host localhost
Upgrade-Insecure-Requests 1
User-Agent Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
Only, if I remove all of the Browsers Chronik in Firefox, then a new authentication request is coming up.
It's probably not the CSRF feature that's setting the login cookie, see: rest-authentication docs, which tells you how to disable the login session.
Disable Sessions
If you don't want to use the recommended config settings:
'user' => [
'enableSession' => false,
'enableAutoLogin' => false,
You can set the values in your controller like:
public function init()
{
parent::init();
Yii::$app->user->enableSession = false;
Yii::$app->user->loginUrl = null;
}
Disable CSRF
If you also want to turn off CSRF (e.g., if you have any web form POSTS to your API), either update the request component in your web config like:
'components' => [
'request' => [
'enableCsrfValidation' => false,
or to turn CSRF off in your controller, use:
$this->enableCsrfValidation = false;
(Obviously you would want to implement your own CSRF protection as applicable if you do turn it off.)

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".

Microsoft Calendar REST API - Access to OData is disabled

I'm trying to access Microsoft's Outlook.com Calendar REST API. I got OAUTH2 authentication set up correctly and have a valid access token and refresh token available.
However, if I try to access the calendar list # https://outlook.office.com with my access token:
GET /api/v1.0/me/calendars HTTP/1.1
Accept: application/json; odata.metadata=none
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciO[...]
the service returns with an 403 Forbidden
HTTP/1.1 403 Forbidden
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
Server: Microsoft-IIS/8.5
Set-Cookie: ClientId=OD6KHQBTKOKMLXUI8OJEG; expires=Wed, 21-Sep-2016 18:37:21 GMT; path=/; secure; HttpOnly
Set-Cookie: exchangecookie=8e4f582170cb445780c7148e9494b293; expires=Thu, 22-Sep-2016 18:37:23 GMT; path=/; HttpOnly
Set-Cookie: ClientId=OD6KHQBTKOKMLXUI8OJEG; expires=Wed, 21-Sep-2016 18:37:21 GMT; path=/; secure; HttpOnly
request-id: 7113f37d-69e0-4f8c-a264-9f3599d47899
X-CalculatedBETarget: CY1PR08MB1801.namprd08.prod.outlook.com
X-BackEndHttpStatus: 403
OData-Version: 4.0
X-AspNet-Version: 4.0.30319
X-DiagInfo: CY1PR08MB1801
X-BEServer: CY1PR08MB1801
X-Powered-By: ASP.NET
X-FEServer: AM3PR04CA0074
X-MSEdge-Ref: Ref A: D69A31E4FAA44258B0B8C351A71D2F9E Ref B: 0D3CA60C0976F50C452293F8CF403D8C Ref C: Tue Sep 22 11:37:23 2015 PST
Date: Tue, 22 Sep 2015 18:37:22 GMT
{"error":{"code":"ErrorAccessDenied","message":"Access to OData is disabled."}}
I played around with Outlook's OAuth Sandbox, where the same request returns a 200 OK with the correct data in the body. Strangely enough, they spot a nice little Show me the cURL! button in the sandbox, but this exact curl command will fail again with a 403 error in my terminal.
What am I missing?
I talked to a Microsoft techie. My problem was, that the REST API is not public (yet) and Microsoft has not yet enabled the API for standard Outlook.com accounts.
I requested an Outlook developer preview account with the REST API enabled by writing an email to outlookdev#microsoft.com
It took some time until I got a response from Microsoft, but using the developer account everything works now as expected.