I've recently seen the access to Cosmos' WebHDFS in FIWARE Lab has been protected with OAuth2. I know I have to add a OAuth2 token to the request in order to continue using WebHDFS, but:
How can I get the token?
How the token is added to the request?
Without the token, the API always returns:
$ curl -X GET "http://cosmos.lab.fi-ware.org:14000/webhdfs/v1/user/gtorodelvalle?op=liststatus&user.name=gtorodelvalle"
Auth-token not found in request header
Yes, now WebHDFS access is protected with OAuth2. This is part of the general mechanism for pretecting REST APIs in FIWARE, which performs authentication and authorization. You can find more details here.
First of all, you must request an OAuth2 token to the Cosmos tokens generator. This is a service running in cosmos.lab.fiware.org:13000. You can do this using any REST client, the easiest way is using the curl command:
$ curl -k -X POST "https://cosmos.lab.fiware.org:13000/cosmos-auth/v1/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=password&username=frb#tid.es&password=xxxxxxxx"
{"access_token": "qjHPUcnW6leYAqr3Xw34DWLQlja0Ix", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "V2Wlk7aFCnElKlW9BOmRzGhBtqgR2z"}
As you can see, your FIWARE Lab credentials are required in the payload, in the form of a password-based grant type.
Once the access token is got (in the example above, it is qjHPUcnW6leYAqr3Xw34DWLQlja0Ix), simply add it to the same WebHDFS request you were performing in the past. The token is added by using the X-Auth-Token header:
$ curl -X GET "http://cosmos.lab.fiware.org:14000/webhdfs/v1/user/frb/path/to/the/data?op=liststatus&user.name=frb" -H "X-Auth-Token: qjHPUcnW6leYAqr3Xw34DWLQlja0Ix"
{"FileStatuses":{"FileStatus":[...]}}
If you try the above request with a random token the server will return the token is not valid; that's because you have not authenticated properly:
$ curl -X GET "http://cosmos.lab.fiware.org:14000/webhdfs/v1/user/frb/path/tp/the/data?op=liststatus&user.name=frb" -H "X-Auth-Token: randomtoken93487345"
User token not authorized
The same way, if using a valid token but trying to access another HDFS userspace, you will get the same answer; that's because you are not authorized to access any HDFS userspace but the one owned by you:
$ curl -X GET "http://cosmos.lab.fiware.org:14000/webhdfs/v1/user/fgalan/path/tp/the/data?op=liststatus&user.name=fgalan" -H "X-Auth-Token: qjHPUcnW6leYAqr3Xw34DWLQlja0Ix"
User token not authorized
IMPORTANT UPDATE:
From summer 2016, cosmos.lab.fiware.org is not workin anymore. Instead, a pair of clusters, storage.cosmos.lab.fiware.org and computing.cosmos.lab.fiware.org have been setup. Regarding the auth server of Cosmos, it currently run in computing.cosmos.lab.fiware.org, port TCP/13000.
The right request must be:
curl -X POST "https://cosmos.lab.fi-ware.org:13000/cosmos-auth/v1/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=password&username=user#domain.com&password=yourpassword" -k
The url was incorrect, the correct is https://cosmos.lab.fi-ware.org:13000
-k is for turn off certificate verification
Related
I am making a call to OAuth API using curl command by passing username,password and getting the bearer token response as JSON which is in the below format.
curl -X POST https://api.mysite.com/oauth/token -u "login:password"
Response
{
"token_type:"Bearer",
"access_token:" "cfdadfa3234sfsdfxx......",
"issued_at":15234234234,
"expires_in":953343434,
"scope": "asdfasd234234234asfasdfasdfaflalsdfkasjfa;sdfassdflj"
}
I need to get only the access_token value which is the bearer token from this curl JSON response and I need to pass as Authorization header to a different apigee gateway hosted api call.
curl -X GET https://apigee.mysite.com/getorderstatus -H "Authroization Bearer ???need to pass bearer token here ???"
How do I parse the JSON and get the bearer token as variable and pass it to the next API call?
I need to do this on the windows server. My environment is only limited to Windows. I can't install packages like jq due to security reason.
The recommended way to extract something from JSON is jq.
However, if you're really sure that the output is always like this, you might
at=$(curl -X POST https://api.mysite.com/oauth/token -u "login:password" | sed -n 's/[ ,"]//g;s/"access_token://p')
curl -X GET https://apigee.mysite.com/getorderstatus -H "$at"
A bash-only solution would be:
curl -X POST https://api.mysite.com/oauth/token -u "login:password" |
while read line ; do
if [[ "$line" == *access_token* ]] ; then
at=${line%\"*}
at=${at##*\"}
curl -X GET https://apigee.mysite.com/getorderstatus -H "$at"
fi
done
Note that, due to the subshell, at is not available outside the loop.
I am a beginner of CAS. I want to get ticket by OpenAPI, and I can provided the user name and password (which can be encrypted). but I don't know how to realize it? Thanks for your advice!
Welcome to CAS!
REST protocol support in Apereo CAS has been available since the early days of CAS 3.x. The REST protocol allows one to model applications as users, programmatically acquiring service tickets to authenticate to other applications. This is achieved by exposing a way to REST-fully obtain a Ticket Granting Ticket and then use that to obtain a Service Ticket.
You can invoke the REST API to authenticate a user and get back a ticket-granting ticket:
curl -k -X POST -H "Content-Type: Application/x-www-form-urlencoded" \
https://sso.example.org/cas/v1/tickets \
-d "username=casuser&password=Mellon"
The ticket-granting ticket that is produced can be used to obtain a service ticket:
curl -X POST -H "Content-Type: Application/x-www-form-urlencoded" \
-H "Accept: application/json" https://sso.example.org/cas/v1/tickets/ \
TGT-2-abcdefg?service=https://your.application.com
ST-1-VGF-yzB8
See this link for more details.
While creating a user using SCIM1.1 endpoint with email.
curl -v -k --user admin:admin --data '{"schemas":[],"name":{"familyName":"gunasinghe","givenName":"hasinitg"},"userName":"hasinitg_sample","password":"hasinitg","emails":[{"primary":true,"value":"hasini_home.com"}]}' --header "Content-Type:application/json" https://localhost:9443/wso2/scim/Users
Created User response:
{"emails":[{"value":"hasini_home.com"}],"meta":{"created":"2018-09-18T15:43:17","location":"https://localhost:9443/wso2/scim/Users/37f051b2-770c-4915-9a3f-623a7404b2a4","lastModified":"2018-09-18T15:43:17"},"schemas":["urn:scim:schemas:core:1.0"],"name":{"familyName":"gunasinghe","givenName":"hasinitg"},"id":"37f051b2-770c-4915-9a3f-623a7404b2a4","userName":"hasinitg_sample"}
Retrieve the USER from SCIM endpoint:
curl -v -k --user admin:admin https://localhost:9443/wso2/scim/Users/37f051b2-770c-4915-9a3f-623a7404b2a4
The response is:
{"meta":{"created":"2018-09-18T15:43:17","location":"https://localhost:9443/wso2/scim/Users/37f051b2-770c-4915-9a3f-623a7404b2a4","lastModified":"2018-09-18T15:43:17"},"schemas":["urn:scim:schemas:core:1.0"],"roles":["Internal/everyone"],"name":{"familyName":"gunasinghe","givenName":"hasinitg"},"id":"37f051b2-770c-4915-9a3f-623a7404b2a4","userName":"hasinitg_sample"}
The email is missing here in the response and My-Sql DB as well. Any idea?
The issue seems to be that if you are sending the email as a JSON object, you have to set the type as well. Following debug log is written when we send an email object without the type attribute.
TID: [-1234] [] [2018-09-19] DEBUG
{org.wso2.carbon.identity.scim.common.utils.AttributeMapper} - Type
attribute cannot be null for sub attribute:
org.wso2.charon.core.attributes.ComplexAttribute#71ebf24c of Complex
MultiValuedAttribute: emails. Skip adding as a claim
Please see the given sample request in the documentation
{"primary":true,"value":"hasini_home.com","type":"home"}
You can use the following request to simply solve your problem.
curl -v -k --user admin:admin --data '{"schemas":[],"name":{"familyName":"gunasinghe","givenName":"hasinitg"},"userName":"hasinitg_sample","password":"hasinitg","emails":"hasini_home.com"}' --header "Content-Type:application/json" https://localhost:9443/wso2/scim/Users
I am trying to implement my own form for changing a user's password. I tried to find an API for changing a user's password in Keycloak but I couldn't find anything in the documentation.
Is there an API for doing it?
you can use PUT /auth/admin/realms/{realm}/users/{id}/reset-password
{id} is the user id in keycloak (not the login)
Here is s sample body.
{ "type": "password", "temporary": false, "value": "my-new-password" }
UPDATE Keycloak 12
The solution described below will no longer work in Keycloak Versions 12 or higher as the developers decided to remove all Account Rest APIs as described in this issue.
Thanks to #Radivarig for pointing this out!
Solution for Keycloak 11
Keycloak recently introduced this feature, but it's currently still in preview and therefore not documented.
To make it work, you need to activate the account_api feature by starting keycloak with the parameter -Dkeycloak.profile.feature.account_api=enabled like so:
bin/standalone.sh -Dkeycloak.profile.feature.account_api=enabled
(source: https://www.keycloak.org/docs/latest/server_installation/index.html#profiles)
After that, you can use POST /auth/realms/your-realm/account/credentials/password and provide the http Header Accept: application/json. The header will make keycloak use a RestAPI-Service which is accepting and returning JSON (instead of the default form-based one which is only accepting x-www-form-urlencoded and returns HTML.)
As Request-Body, provide a JSON like this:
{
"currentPassword": "oldPassword",
"newPassword": "newPassword",
"confirmation": "newPassword"
}
A full example with curl would look like this:
curl --request POST 'https://path-to-your-host.com/auth/realms/your-realm/account/credentials/password' \
--header 'Accept: application/json' \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"currentPassword": "oldPassword",
"newPassword": "newPassword",
"confirmation": "newPassword"
}'
Note that - as written above - this feature is still in preview and might change in the future. So use it with caution!
Rather than specifying a new password manually a better security practice is to use the
PUT /auth/admin/realms/{realm}/users/{id}/execute-actions-email
admin call with "UPDATE_PASSWORD" as the required action. This causes Keycloak to send an email to the user that gives a magic link for the user to set a new password.
Note: {id} is the user id in keycloak (not the login)
As Keycloak Admin REST API suggests you can send a PUT requqest to keycloakEndpoint/auth/{realm}/users/{id}/execute-actions-email to execute actions against user. you need to obtain an admin access token as described here
TL;DR: The better way to do it via web app
keycloak.login({
action: "UPDATE_PASSWORD",
})
For more info: https://www.keycloak.org/docs/latest/securing_apps/#login-options
:-)
#!/bin/bash
#CHANGE ADMIN PASSWORD
apt update
apt install -y curl jq
KEYCLOAK_HOST=http://127.0.0.1:8080
ADMIN_USER_OLD_PASSWORD=
ADMIN_USER_NEW_PASSWORD=
TOKEN=$(curl -s -X POST -H 'Content-Type: application/x-www-form-urlencoded' -d "username=admin&password=$ADMIN_USER_OLD_PASSWORD&client_id=admin-cli&grant_type=password" "$KEYCLOAK_HOST/auth/realms/master/protocol/openid-connect/token" | jq -r ".access_token" ;)
ADMIN_USER_ID=$(curl -s -X GET -H "Authorization: Bearer $TOKEN" -H "Content-type: application/json;charset=UTF-8" -H 'Accept: application/json' "$KEYCLOAK_HOST/auth/admin/realms/master/users" | jq -r '.[] | select(.username=="admin") | .id' )
curl -s -X PUT -H "Authorization: Bearer $TOKEN" -H "Content-type: application/json;charset=UTF-8" -H 'Accept: application/json' "$KEYCLOAK_HOST/auth/admin/realms/master/users/$ADMIN_USER_ID/reset-password" -d "{\"type\":\"password\",\"value\":\"$ADMIN_USER_NEW_PASSWORD\",\"temporary\":false}"
constructor(
private keycloakService: KeycloakService,
) { }
onPasswordChangeButtonClick(){
this.keycloakService.login({
action: "UPDATE_PASSWORD",
});
}
please try this approach to change the password
This worked for me:
https://github.com/keycloak/keycloak/pull/7393#issuecomment-1103532595
But you have to see if you can use a custom theme, if you want a different form than the default from keycloak.
No, OAuth and OpenID Connect protocols doesn't define such feature and Keycloak also doesn't have ability to do this on user's behalf. There is a server-to-Server Admin API that alows to change the user's password or reset it but you can't call it from GUI.
But the Keycloak provides some kind of "My Account Page" by url like http://localhost:8080/auth/realms/your-realm/account/ - replace your-realm part of URL and just redirect a user to it.
In documentation it called User Account Service
Also if you use auto discovery you can obtain the url by reading account-service from JSON by URL http://localhost:8080/auth/realms/your-realm
Using WebHDFS API of Cosmos generates an expired certificate response.
Using this url: https://cosmos.lab.fi-ware.org:13000/
we can see certificate seems expired
Do we need updated certificate or any way to go around this problem?
The certificate must be renewed, for sure. In the meantime, you can simply ignore the certificate. If you are using curl, use the -k option:
$ curl -k -X POST "https://cosmos.lab.fiware.org:13000/cosmos-auth/v1/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=password&username=frb#tid.es&password=MY_PASSWORD_IS_PRIVATE"