orderprocess
, which related to some other activity I’m involved in, and simpleworkflow
which we’ll use for these experiments. It’s just a definition that starts and then immediately ends.-> cf s
Getting services in org p2001351149trial / space dev ...
name service plan bound apps last operation broker upgrade available
portal_resources_workflowtiles portal standard workflowtilesApprouter, workflowtilesFLP create succeeded sm-portal-fbae912e-4046-4304-90ad-b6d8ed1fa3be
uaa_workflowtiles xsuaa application workflowtilesApprouter, workflowtilesFLP create succeeded sm-xsuaa-9ef36350-f975-4194-a399-54db361e79b5
workflow workflow lite workflowtilesApprouter, workflowtilesFLP update succeeded sm-workflow-broker-d2b48385-f83e-4601-9830-0db967aaa2f5
workflowtiles_html5_repo_runtime html5-apps-repo app-runtime workflowtilesApprouter create succeeded sm-html5-apps-repo-sb-ebcb2b69-24a5-408e-be00-02066b302b78
-> cf service-keys workflow
Getting keys for service instance workflow ...
name
OrderProcess-workflow-credentials
SimpleWorkflow-workflow-credentials
SimpleWorkflow-workflow-credentials
service key so that we can dig into those details programatically later on:-> cf service-key workflow SimpleWorkflow-workflow-credentials > keys.json
cf
command spat out when executing this request (cf
is great as it’s a command line tool, but I do think it lacks a certain finesse when it comes to usability, and unfortunately the cf curl
approach, using a completely different API and therefore mental model, is not a good workaround).-> cf service-key workflow SimpleWorkflow-workflow-credentials > keys.json
cf
command spat out when executing this request (cf
is great as it’s a command line tool, but I do tcf curl
approach, using a completely different API and therefore mental model, is not a{
"content_endpoint": "https://api.workflow-sap.cfapps.eu10.hana.ondemand.com/workflow-deploy/rest/internal/v1",
"endpoints": {
"workflow_odata_url": "https://api.workflow-sap.cfapps.eu10.hana.ondemand.com/workflow-service/odata",
"workflow_rest_url": "https://api.workflow-sap.cfapps.eu10.hana.ondemand.com/workflow-service/rest"
},
"html5-apps-repo": {
"app_host_id": "2834263a-6e04-4f43-876a-67b81f32306e,1a5b93af-f1af-4acf-aee0-8c6cc8d3f315,8964e911-e35d-4cfd-972e-08e681a2df0f,9ea7410f-80ea-4b19-bbf0-4fca238ef098&qu
ot;
},
"saasregistryappname": "workflow",
"sap.cloud.service": "com.sap.bpm.workflow",
"uaa": {
"apiurl": "https://api.authentication.eu10.hana.ondemand.com",
"clientid": "sb-clone-deadbeef-03b2-46bb-bd3d-f00b7d2db0d2!b37882|workflow!b10150",
"clientsecret": "1090976f-982a-3723-9a5d-723c913aba14$In4EKA1s5AIcfqo_juwHpKwGgh3o_bpYfeyIF0JE1Zg=",
"identityzone": "p2001351149trial",
"identityzoneid": "0a25d69a-6331-312a-bea9-1e90dc1f941f",
"sburl": "https://internal-xsuaa.authentication.eu10.hana.ondemand.com",
"tenantid": "0a25d69a-6331-47ff-bea9-1e90dc1f941f",
"tenantmode": "dedicated",
"uaadomain": "authentication.eu10.hana.ondemand.com",
"url": "https://p2001351149trial.authentication.eu10.hana.ondemand.com",
"verificationkey": "-----BEGIN PUBLIC KEY-----MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwThn6OO9kj0bchkOGkqYBnV1dQ3zU/xtj7Kj7nDd8nyRMcEWCtVzrzjzh- [ ] sRhlrzlRIEY82
wRAZNGKMnw7cvCwNixcfcDJnjzgr2pJ+5/yDZUc0IXXyIWPZD+XdL+0EogC3d4+fqyvg/BF/F0t2hKHWr/UTXE6zrGhBKaL0d8rKfYd6olGWigFd+3+24CKI14zWVxUBtC+P9Fhngc9DRzkXqhxOK/EKn0HzSgotf5duq6Tmk9DCNM4sLW4+ERc
6xzrgbeEexakabvax/Az9WZ4qhwgw+fwIhKIC7WLwCEJaRs...=-----END PUBLIC KEY-----",
"xsappname": "clone-b34de1f8-03b2-12de-bd3d-f00b7d2db0d2!b37882|workflow!b10150"
}
}
endpoints.workflow_rest_url
is the base URL for the resource server (the Workflow API endpoint, in this case)uaa.clientid
is the client ID to be used in the flowuaa.clientsecret
is the client secret to be used in the flowuaa.url
is the based URL for the authorisation server (for requesting tokens and so on)skv
function we created in the previous episode, this time allowing me to use it on different JSON files. Here’s what the definition looks like now:skv () { jq -r ."$2" "$1".json; }
uaa.url
value from the keys file like this:-> skv keys uaa.url
https://p2001351149trial.authentication.eu10.hana.ondemand.com
-> cf update-service workflow -c '{"authorities":[]}'
Updating service instance workflow ...
OK
~/.netrc
file with the client ID and secret to be used in a Basic Authentication header in calls to the authorisation server endpoint:machine p2001351149trial.authentication.eu10.hana.ondemand.com
login sb-clone-deadbeef-03b2-46bb-bd3d-f00b7d2db0d2!b37882|workflow!b10150
password 1090976f-982a-3723-9a5d-723c913aba14$In4EKA1s5AIcfqo_juwHpKwGgh3o_bpYfeyIF0JE1Zg=
-> curl -n \
> -v \
> -X POST \
> "$(skv keys uaa.url)/oauth/token?grant_type=client_credentials" > token.json
token.json
file containing the results of this call into a separate folder signifying the flow that was used. Also, to have the service key details (in the keys.json
file we wrote to earlier) in the same directory, but not repeated, we make a symbolic link, ending up with something like this:├── client_credentials
│ ├── keys.json -> ../keys.json
│ └── token.json
└── keys.json
token.json
file, we see that we have these properties returned to us:access_token
: the token itselftoken_type
: the type of token (it’s a bearer token)expires_in
: how long the token lives for (we had a fun time guessing what the 43199 value represented, back in Episode 52 - see the annotations blog post for more on that)scope
: an indication of the access we have with this particular token, in the form of scopes authorised by the UAAjti
: not mentioned here but this is a unique identifier for this tokenscope
property using some basic tools, like this:-> skv token scope | tr ' ' '\n' | sort
uaa.resource
workflow!b10150.FORM_DEFINITION_DEPLOY
workflow!b10150.TASK_DEFINITION_GET
workflow!b10150.TASK_GET
workflow!b10150.WORKFLOW_DEFINITION_DEPLOY
-> curl -H "Authorization: Bearer $(skv token access_token)" \
> "$(skv keys endpoints.workflow_rest_url)/v1/workflow-definitions" \
> | jq .
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 65 100 65 0 0 137 0 --:--:-- --:--:-- --:--:-- 137
{
"error": {
"message": "User does not have sufficient privileges."
}
}
-s
switch).-> cf update-service workflow \
> -c '{"authorities":["WORKFLOW_DEFINITION_GET"]}'
Updating service instance workflow ...
OK
access_token
, gives us a result that we could have predicted, i.e. we still get the “User does not have sufficient privileges” message. This is of course because when minted, that token didn’t include the scope we’ve just set.-> curl -s \
> -H "Authorization: Bearer $(skv token access_token)" \
> "$(skv keys endpoints.workflow_rest_url)/v1/workflow-definitions" \
> | jq .
[
{
"id": "simpleworkflow",
"version": "1",
"name": "simpleworkflow",
"createdBy": "sb-clone-deadbeef-03b2-46bb-bd3d-f00b7d2db0d2!b37882|workflow!b10150",
"createdAt": "2020-03-20T05:57:50.933Z",
"jobs": []
},
{
"id": "orderprocess",
"version": "8",
"name": "orderprocess",
"createdBy": "sb-clone-deadbeef-03b2-46bb-bd3d-f00b7d2db0d2!b37882|workflow!b10150",
"createdAt": "2020-03-18T14:29:16.411Z",
"jobs": []
}
]
-> curl -n \
> -v \
> "$(skv keys uaa.url)/oauth/token?grant_type=client_credentials" > token.json
-> curl -v \
> -d "grant_type=client_credentials&client_id=$(skv keys uaa.clientid)&client_secret=$(skv keys uaa.clientsecret)" \
> "$(skv keys uaa.url)/oauth/token" > token.json
-> set -o vi
-> cf update-service workflow -c '{"authorities": ["WORKFLOW_DEFINITION_GET", "WORKFLOW_INSTANCE_START"]}'
Updating service instance workflow ...
OK
-> curl -v \
> -d "grant_type=client_credentials&client_id=$(skv keys uaa.clientid)&client_secret=$(skv keys uaa.clientsecret)" \
> "$(skv keys uaa.url)/oauth/token" > token.json
/v1/workflow-definitions
API endpoint, like this:-> curl -s \
> -H "Content-Type: application/json" \
> -H "Authorization: Bearer $(skv token access_token)" \
> -d '{"definitionId":"simpleworkflow", "context":{"number":42}}' \
> "$(skv keys endpoints.workflow_rest_url)/v1/workflow-instances" | jq .
{
"id": "1fce48e8-6d08-11ea-855a-eeee0a94224d",
"definitionId": "simpleworkflow",
"definitionVersion": "1",
"subject": "simpleworkflow",
"status": "RUNNING",
"businessKey": "",
"startedAt": "2020-03-23T13:13:44.900Z",
"startedBy": "sb-clone-deadbeef-03b2-46bb-bd3d-f00b7d2db0d2!b37882|workflow!b10150",
"completedAt": null
}
authorization_code/
that we create in a similar way to the first one, so we now have:.
├── authorization_code
│ └── keys.json -> ../keys.json
├── client_credentials
│ ├── keys.json -> ../keys.json
│ └── token.json
└── keys.json
/oauth/authorize
as opposed to what we’ve seen thus far, i.e. /oauth/token
. This is because we’re not asking for a token directly at this stage.~/.bash_aliases
, as we’ll need to URL encode the values in the URL’s query string:-> cat ~/.bash_aliases
alias urldecode='python3 -c "import sys, urllib.parse as ul; print(ul.unquote_plus(sys.argv[1]))"'
alias urlencode='python3 -c "import sys, urllib.parse as ul; print (ul.quote_plus(sys.argv[1]))"'
-> echo "$(skv keys uaa.url)/oauth/authorize?client_id=$(urlencode `skv keys uaa.clientid`)&response_type=code"
https://p2001351149trial.authentication.eu10.hana.ondemand.com/oauth/authorize?client_id=sb-clone-de...
zCyAM2lqaQ
for an access token. So we do that:-> curl -n \
> -v \
> "$(skv keys uaa.url)/oauth/token?grant_type=authorization_code&code=zCyAM2lqaQ"
token.json
file (remember, we’re in the authorization_code/
directory here too).-> cd ../client_credentials/
-> skv token scope | tr ' ' '\n' | sort
uaa.resource
workflow!b10150.FORM_DEFINITION_DEPLOY
workflow!b10150.TASK_DEFINITION_GET
workflow!b10150.TASK_GET
workflow!b10150.WORKFLOW_DEFINITION_DEPLOY
workflow!b10150.WORKFLOW_DEFINITION_GET
workflow!b10150.WORKFLOW_INSTANCE_START
-> skv token scope | tr ' ' '\n' | sort
openid
uaa.user
workflow!b10150.AUTHORIZE_WITH_INSTANCE_ROLES
workflow!b10150.FORM_DEFINITION_DEPLOY
workflow!b10150.FORM_DEFINITION_GET_MODEL
workflow!b10150.FORM_DEFINITION_GET_MODEL_ANY
workflow!b10150.IMPERSONATION_TOKEN_GET
workflow!b10150.READ_FEATURE_FLAGS
workflow!b10150.RETRIEVE_XSRF_TOKEN
workflow!b10150.TASK_COMPLETE_ANY
workflow!b10150.TASK_DEFINITION_QUERY_ANY
workflow!b10150.TASK_GET_ATTRIBUTES_ANY
workflow!b10150.TASK_GET_CONTEXT_ANY
workflow!b10150.TASK_GET_FORM
workflow!b10150.TASK_GET_FORM_MODEL
workflow!b10150.TASK_MANAGE_OWN
workflow!b10150.TASK_PATCH_ANY
workflow!b10150.TASK_QUERY_ANY
workflow!b10150.WORKFLOW_DEFINITION_DEPLOY
workflow!b10150.WORKFLOW_DEFINITION_GET_MODEL
workflow!b10150.WORKFLOW_DEFINITION_QUERY_ANY
workflow!b10150.WORKFLOW_DEFINITION_VALIDATE
workflow!b10150.WORKFLOW_INSTANCE_CANCEL
workflow!b10150.WORKFLOW_INSTANCE_ERROR_MESSAGES_QUERY
workflow!b10150.WORKFLOW_INSTANCE_GET_ATTRIBUTES
workflow!b10150.WORKFLOW_INSTANCE_GET_CONTEXT
workflow!b10150.WORKFLOW_INSTANCE_QUERY_ANY
workflow!b10150.WORKFLOW_INSTANCE_QUERY_EXECUTION_LOGS
workflow!b10150.WORKFLOW_INSTANCE_QUERY_ROLES
workflow!b10150.WORKFLOW_INSTANCE_RETRY_RESUME
workflow!b10150.WORKFLOW_INSTANCE_START
workflow!b10150.WORKFLOW_INSTANCE_SUSPEND
workflow!b10150.WORKFLOW_INSTANCE_UPDATE_ROLES
workflow
role collection, which we look at briefly now.-> curl -s \
> -H "Content-Type: application/json" \
> -H "Authorization: Bearer $(skv token access_token)" \
> -d '{"definitionId":"simpleworkflow", "context":{"number":43}}' \
> "$(skv keys endpoints.workflow_rest_url)/v1/workflow-instances" | jq .
{
"id": "1fce48e8-6d08-11ea-855a-209327de311",
"definitionId": "simpleworkflow",
"definitionVersion": "1",
"subject": "simpleworkflow",
"status": "RUNNING",
"businessKey": "",
"startedAt": "2020-03-23T13:13:44.900Z",
"startedBy": "qmacro+workflowcodejam@gmail.com",
"completedAt": null
}
startedBy
property, of course! Instead of referring to the non-human client ID, it’s referring to me, the human who actually started the workflow instance.workflow!b10150.WORKFLOW_INSTANCE_START
echo
command as before:-> echo "$(skv keys uaa.url)/oauth/authorize?client_id=$(urlencode `skv keys uaa.clientid`)&response_type=code"
https://p2001351149trial.authentication.eu10.hana.ondemand.com/oauth/authorize?client_id=sb-clone-de...
-> skv token scope | tr ' ' '\n' | sort
openid
uaa.user
workflow!b10150.AUTHORIZE_WITH_INSTANCE_ROLES
workflow!b10150.FORM_DEFINITION_DEPLOY
workflow!b10150.FORM_DEFINITION_GET_MODEL
workflow!b10150.FORM_DEFINITION_GET_MODEL_ANY
workflow!b10150.IMPERSONATION_TOKEN_GET
workflow!b10150.READ_FEATURE_FLAGS
workflow!b10150.RETRIEVE_XSRF_TOKEN
workflow!b10150.TASK_COMPLETE_ANY
workflow!b10150.TASK_DEFINITION_QUERY_ANY
workflow!b10150.TASK_GET_ATTRIBUTES_ANY
workflow!b10150.TASK_GET_CONTEXT_ANY
workflow!b10150.TASK_GET_FORM
workflow!b10150.TASK_GET_FORM_MODEL
workflow!b10150.TASK_MANAGE_OWN
workflow!b10150.TASK_PATCH_ANY
workflow!b10150.TASK_QUERY_ANY
workflow!b10150.WORKFLOW_DEFINITION_DEPLOY
workflow!b10150.WORKFLOW_DEFINITION_GET_MODEL
workflow!b10150.WORKFLOW_DEFINITION_QUERY_ANY
workflow!b10150.WORKFLOW_DEFINITION_VALIDATE
workflow!b10150.WORKFLOW_INSTANCE_CANCEL
workflow!b10150.WORKFLOW_INSTANCE_ERROR_MESSAGES_QUERY
workflow!b10150.WORKFLOW_INSTANCE_GET_ATTRIBUTES
workflow!b10150.WORKFLOW_INSTANCE_GET_CONTEXT
workflow!b10150.WORKFLOW_INSTANCE_QUERY_ANY
workflow!b10150.WORKFLOW_INSTANCE_QUERY_EXECUTION_LOGS
workflow!b10150.WORKFLOW_INSTANCE_QUERY_ROLES
workflow!b10150.WORKFLOW_INSTANCE_RETRY_RESUME
workflow!b10150.WORKFLOW_INSTANCE_SUSPEND
workflow!b10150.WORKFLOW_INSTANCE_UPDATE_ROLES
workflow!b10150.WORKFLOW_INSTANCE_START
scope. This is a direct result of the removal of the WorkflowInitiator role from the workflow role collection assigned to me.{
"error": {
"message": "User does not have sufficient privileges."
}
}
token.json
file, remembering which properties are in there:-> jq keys token.json
[
"access_token",
"expires_in",
"id_token",
"jti",
"refresh_token",
"scope",
"token_type"
]
jq
in the live stream but it’s useful for us here).-> curl -n -v "$(skv keys uaa.url)/oauth/token?grant_type=refresh_token&refresh_token=$(skv token refresh_token)" > refreshed-token.json
grant_type
query string parameter is most likely why “Refresh Token” is listed on the OAuth 2.0 website as a first class grant type citizen.)-> curl -s -H "Authorization: Bearer $(skv token access_token)" "$(skv keys endpoints.workflow_rest_url)/v1/workflow-definitions" | jq .
[
{
"id": "simpleworkflow",
"version": "1",
"name": "simpleworkflow",
"createdBy": "sb-clone-b34de1f8-03b2-46bb-bd3d-f00b7d2db0d2!b37882|workflow!b10150",
"createdAt": "2020-03-20T05:57:50.933Z",
"jobs": []
},
{
"id": "orderprocess",
"version": "8",
"name": "orderprocess",
"createdBy": "sb-clone-b34de1f8-03b2-46bb-bd3d-f00b7d2db0d2!b37882|workflow!b10150",
"createdAt": "2020-03-18T14:29:16.411Z",
"jobs": []
}
]
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
23 | |
14 | |
13 | |
13 | |
11 | |
10 | |
9 | |
9 | |
8 | |
8 |