Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

SAP Developer Challenge - APIs - Task 9 - Create a service key for API endpoints and auth info

qmacro
Developer Advocate
Developer Advocate
12,247

(Check out the SAP Developer Challenge - APIs blog post for everything you need to know about the challenge to which this task relates!)

This task follows on from the previous task and moves you one step closer in your steady journey of enlightenment, moving towards calling an API endpoint on SAP BTP.

Background

In the previous task, you created an instance of the SAP Cloud Management Service. Why? Because this service provides facilities to manage resources on SAP BTP, and those facilities include the APIs you've been learning about in previous tasks in this group. But merely having an instance of the service isn't going to get you far.

To consume a service's facilities, more is needed. In an application context, an app is bound to a service instance, and, once bound, can consume those facilities. The same goes for API calls. What's needed are a couple of things - endpoint information and credential information.

So. You've done step 1 of the steps introduced in the previous task. Now you're tackling step 2.

  1. create an instance of the SAP Cloud Management Service, with a plan that contains the appropriate scope(s) that you need
  2. create a service key based on that instance
  3. use the details in the service key to request an access token
  4. use the access token thus obtained to authenticate a call to the API endpoint

Endpoint information

First, you need some information on the API endpoints. This is because information you found on the SAP Business Accelerator Hub for the endpoint you're going to call:

GET /accounts/v1/directories/{directoryGUID}

only presents a relative path (/accounts/v1/directories/{directoryGUID}). For it to be a callable endpoint it needs of course to be prefixed with the rest of the URL - the scheme and fully qualified domain name, at least.

To be precise, the http (or https) part of a URL is known as the "scheme". See the List of URI schemes Wikipedia page for more information. And while we're in precision mode, are you wondering about the difference between URL and URI? They're not the same. URLs are a subset of URIs. A URI (Uniform Resource Identifier) is just a string that identifies a resource. A URL (Uniform Resource Locator) identifies a resource, but also allows you to locate that resource. Yes, the clue really is in the name(s) 🙂

Credential information

As well as endpoint information, you also need access, in the form of authentication. What form that takes, and how it's used, is sometime service-specific. But generally there will be a requirement to provide credentials in the API call itself.

You've done this already in a previous task, in that you provided an API key in an "APIKey" header, when you made the call to the country date format API endpoint in Task 5 - Call the country date format API endpoint

More commonly, the standard Authorization HTTP header is used to convey the credentials. The value for this header is usually made up of two parts, and formed like this:

Authorization: <auth scheme> <auth details>

In the bad (good?) old days, you may well have used Basic Authentication, i.e. provided a username and password, joined with a colon, and encoded in Base64. Here's an example of that:

Authorization: Basic d2VsbC1kb25lOnlvdXItY3VyaW9zaXR5LWlzLWdyZWF0IQ==

Note that encoding != encrypting, which means that this approach was somewhat insecure, in that anyone who could see the HTTP request headers could obtain those credentials. Moreover, obtaining credentials as fundamental as username and password means a world of pain if they are ever compromised.

This is why OAuth, which focuses on obtaining and using tokens as credentials, is a far better approach for managing the request and use of credentials. Generally, tokens are obtained up front (sometimes requiring username and password style information) and then also eventually expire (they can be refreshed using a similar but simpler approach to the original way they were obtained). Expired tokens are no use to anyone, and if a token is compromised, it can be expired a lot easier, and with far fewer side effects (on other consumers using the same credential approach) than expiring or invalidating a compromised username and password.

Anyway, getting back to this Authorization header, there are other more secure auth schemes that are standard and used with this header, and you'll be working towards using such a scheme in the next task.

Service keys

This endpoint and credential information, essential to consume a service's facilities, is provisioned in so-called "service keys", that relate to an instance of a service.

Creating a service key effectively brings about the creation of credentials that are then valid for use by the consumer. Once a service key has been created, it can be retrieved, and will contain the credentials, plus information on the endpoints.

When an app is bound to a service instance, similar information is created (this is why one can equate the term "service key" with "binding" and why different cloud platform runtimes use these terms almost interchangeably).

Your task

Your task, then, is to create a service key for the instance of the SAP Cloud Management Service you created in the previous task. You should use the cf CLI to do this. You'll have to give the service key a name; it doesn't really matter too much what you call it; the name "sk" will do fine for the purpose of this task, but in the end, you can choose.

Once you have created a service key, you should retrieve it, and take a look at the information, which will be in JSON. You'll need to compose a value (to send to the hash service) based on some of the property names in this JSON data.

That value should be a sorted list of the endpoint property names (not their values), separated by commas. To be clear, these endpoint property names are the keys of the key/value pairs inside the credentials.endpoints node, and they all end in _url.

Once you have composed that value, you should hash it and share as a new reply to this discussion thread, as always, and as described in Task 0.

Oh, and while it's not part of this task's requirements, you might as well save the JSON in in a file, too, because you're going to need it again in the next task!

Hints and tips

You're strongly encouraged to use the cf CLI for this task. This is for the usual obvious reasons, which are:

  • the command line is an extremely powerful and flexible environment
  • using and combining tools in a command line (shell) context is the ultimate in power and flexibility
  • you can script usage of such tools, embracing the facilities of the command line to build automation
  • it helps you get closer to the metal, to explore the details of the services and runtimes you're consuming

If, however, you do wish to use the GUI, in the form of the SAP BTP Cockpit, then go ahead. The cockpit, or any GUI for that matter, is great for one-off and occasional tasks, but it's no match for the power of the command line. You may wish to read the blog post Managing resources on SAP BTP – what tool do I choose? which touches on this topic.

If you're using the cf CLI, you'll want to avail yourself of the commands within the "Services integration" section.

Services integration:
  marketplace,m        create-user-provided-service,cups
  services,s           update-user-provided-service,uups
  create-service,cs    create-service-key,csk
  update-service       delete-service-key,dsk
  delete-service,ds    service-keys,sk  service              service-key
  bind-service,bs      bind-route-service,brs
  unbind-service,us    unbind-route-service,urs

Note that once you've created your service key, and are looking at its output with:

cf service-key <service-instance> <service-key>

you'll notice that the output is JSON. Great! You can parse it and programatically generate the value you need to send to the hash service for your task reply.

However, note that the command is not entirely well-behaved, emitting "helpful" information just before the JSON itself. This is ultimately against the spirit of the UNIX command line philosophy. Here's an example of the output of such a command (some of the properties in the JSON have been removed for brevity):

Getting key cis-central-sk for service instance cis-central as dj.adams@sap.com...

{
  "credentials": {
    "endpoints": "..."
    "grant_type": "user_token",
    "sap.cloud.service": "com.sap.core.commercial.service.central",
    "uaa": {
      "uaadomain": "authentication.eu10.hana.ondemand.com",
      "xsappname": "ut-f86082c9-7fbf-4e1e-8310-f5d018dab542-clone!b254751|cis-central!b42",
      "xsmasterappname": "cis-central!b42",
      "zoneid": "7da58aab-6c60-4492-a95b-b1ed3139e242"
    }
  }
}

The first two lines ("Getting key ...", and the empty line) are not JSON. This means you will have to clean up the output of the command before processing it as JSON (and saving it to a file).

Note that the value of the endpoints property in the above output example is given as "..." - this is just for brevity in illustration; the value is in fact an object, containing properties, the names of which should be of interest to you for this task!

Note also that this example output also reminds us of one of the breaking changes between version 7 and version 8 of the cf CLI that were mentioned in the previous task. It's the advent of version 8 that brought along the outermost wrapping of the data within a new credentials property. Before version 8, that node does not exist in the JSON.

57 REPLIES 57

ajmaradiaga
Developer Advocate
Developer Advocate
0 Kudos
9,539

93c6abf00d0df772b95bfb04e8a707aea2d97174f8f9c5ae8932f687ad552003

vladimirs_semikins
Active Contributor
0 Kudos
9,516

7b7c77832cfc9ece13c674f39172075309ef1e60e803bdd398144dbb807d54ea

0 Kudos
8,823

🛸 UFO said that my curiosity is great 🐣

ceedee666
Active Contributor
0 Kudos
9,506
e192b00d1f344a49cdd3c78b2b67570df5620e2b9c7d3ee879633895a1e03d2c

Tomas_Buryanek
Active Contributor
0 Kudos
9,495

4d02269a4ac5676b39992ad9bd617da06304339596a23cc7b39cc274047cdc7a

-- Tomas --

salilmehta01
Associate
Associate
0 Kudos
9,480

dbf8bc5b50fb7a543bd550801d49dc57cc4ec7f60d6319fb6b1e298e6aa3ad01

harsh_itaverma
Participant
0 Kudos
9,439

c14d1ac34564471e7573f53dc835478d1390e139f3b03566aece9052f8c9f6bc

8,736

Posted the wrong reply earlier, as I had each key inside the double quotes.
I tried using jq this time and found it very easy than writing JS code to fetch the keys

SandipAgarwalla
Active Contributor
0 Kudos
9,436

a342c637822668bb341b3cebe005d7999c370171fe367f686dca3a602fc5a1c8

SandipAgarwalla
Active Contributor
0 Kudos
9,444

I have a question. In the Service Key JSON file, which url represents the Access Token URL and which url represents the actual API URL? 

9,434

Kudos for asking questions! This is great. The actual API URL, or at least the "base" for it, is in the `.credentials.endpoints` object in the service key data, and the URL of the authorization server, where you will (in the next task!) be making a request for an access token, is in the `.credentials.uaa` object, specifically the `.credentials.uaa.url` property 👍

0 Kudos
8,842

Thanks DJ

Finally, I was able to get a Access Token from a nodejs program. Next would be to use this token to call the Accounts API. 

Ashok459
Participant
0 Kudos
9,422

090d547f847d7ad1de45ca80a4b8d7f37b6df6312e9a14220c54d6fb7e10d176

PriyankaChak
Active Contributor
0 Kudos
9,200

Regarding this point 'URLs are a subset of URIs' - I think it should be 'URIs are a subset of URLs'.

qmacro
Developer Advocate
Developer Advocate
0 Kudos
9,182

Why do you think that, @PriyankaChak ?

PriyankaChak
Active Contributor
9,173

Sorry, my bad. The statement 'URLs are a subset of URIs' seems correct. I previously misinterpreted resource path of URL as URI.

bztoy
Participant
0 Kudos
9,188

d716931f5c02842c7ad9dd290151dde7a4de18754f6741b709bc95c30287d3fe

9,168

you always learn new thing from DJ's article, this is fact. 😉

I just know that http(s) is URI schemes and after read the provided link there are also 2 schemas that has the same name (chrome). 🤔

UweFetzer_se38
Active Contributor
0 Kudos
9,174

18974047f4606c79341dab5a56adbb9742bc9688a66da19bcf1be4ab1381b352

9,169

CLI + Notepad++ (sorry no time for pipes, jq or Python today)

cdias
Product and Topic Expert
Product and Topic Expert
0 Kudos
9,168

5e4c05b2540229e4f274b31c9c4d2da06248c703f8a648f460fd8bbc0a7e6974

PriyankaChak
Active Contributor
0 Kudos
9,160

821dc86fef8a9a9258ee9bb7c0159d3879400185723c807cc7dfe8cba07bd4c4

thomas_jung
Developer Advocate
Developer Advocate
0 Kudos
9,098

51cf0567fb18d827a496c3d38176d0d1ec5d62c2f7f54460315fa6125bbbcfc6

szeteng00
Explorer
0 Kudos
9,063

e6d970696c0e642887ed45163831c53ee4fdefe7eaf4b5bb3e32df7b372b4cce

choujiacheng
Explorer
0 Kudos
9,036

83ad1b46a455152d8206733fca0191128ddf802ed2a235fd70320be5e65ec209

nicoschoenteich
Developer Advocate
Developer Advocate
0 Kudos
8,878

b6e0368f0184b5f92d7acc25ce0bad25322bed8bf90da8ee7ba88b580e7970ee

tobiasz_h
Active Participant
0 Kudos
8,840

b6d82b4c5fbb51d27af9e8eb216307a863830e9d195604099fd899cf0f3e60bb

shotokka
Explorer
0 Kudos
8,840

83595968e6a6b1adddd5f029fddc051c56253a5d5751a1109772e9f1d25009c8

Nicolas
Active Contributor
0 Kudos
8,829

39e64168549ee67252965a18dc36d33ac949aa05ea3a4e0ac57400a5b778857b

ADR
Participant
0 Kudos
8,822

dec86f93e84f562703e6c5ce0af65ef45e6367a5edcb47ecd6e206807e93c4b9

Dan_Wroblewski
Developer Advocate
Developer Advocate
0 Kudos
8,796

2164db5d0bc323cddf8c3193dd554d45945c7cbd6891290f361b84fbd6e77873




--------------
See all my blogs and connect with me on Twitter / LinkedIn

kasch-code
Participant
0 Kudos
8,744

596470e9d410c5517abdbd2429bc11819e1e7070d13b5f90154fa9917a773444

prachetas
Participant
0 Kudos
8,341

897e2f40594291ee296f2a9a0e297a695d8abef2a3f15693077fb50bf9ff7276

garyzuo
Explorer
0 Kudos
8,258

1f0e3ccbeb56cf7561a917b62b441c8925cc0b467b869bbaef5a407d2aa12466

geek
Participant
0 Kudos
8,246

e5a837bc179fb8f45575d9001727d0ab86b8bc41e7fd7c89226d768015c606e0

emiliocampo
Explorer
0 Kudos
8,034

64a70cdaeec1d9cf5be0250525c44d5639dedb719c67c317177dcb53797c181e

berserk
Explorer
0 Kudos
7,974

04473bfd4d5c17810e38d35f750371606589576956aed13b210678a8a2d6ad08

former_member136915
Product and Topic Expert
Product and Topic Expert
0 Kudos
7,944
75ff049689fbda6b6b2b99c7dba0911ee131d407cea421b7a17775ff3e5d843b

sabarna17
Contributor
0 Kudos
7,790

64728490339def647ae604097ad342670f8574ba7b0e253c835036c95310ee70