Skip to Content
Technical Articles

Connecting visual studio code with cloud platform

A few weeks ago I decided to try to connect my visual studio code plugin with my cloud platform trial.

That required to implement oauth2 authentication, which I never coded before. It’s actually pretty simple, you need to get an authorisation token (full source here):

import ClientOAuth2 from "client-oauth2"
import opn from "open"

const oa = new ClientOAuth2({
    authorizationUri: `${uaaUrl}/oauth/authorize`,
    accessTokenUri: `${uaaUrl}/oauth/token`,
    redirectUri, // a local webserver you set up in node
    clientId,
    clientSecret
  })

// open the login page in a browser
opn(oa.code.getUri()) 
// wait until the local webserver is called
const url = (await callbackRequest).url
const token = await oa.code.getToken(url)

Also that requires a service key containing the connection details required.

This will open a tab in your browser to ask you to authorise the application (or authorise it straight away if you’re logged in already)

Once you have a token you just add it to your requests and you’re authenticated:

await got(url,{
    headers:{ Authorization: `bearer ${token.accessToken}` } } )

If you store the token you can even refresh it without asking for user permission:

const oauth = new ClientOAuth2({
  authorizationUri: `${uaaUrl}/oauth/authorize`,
  accessTokenUri: `${uaaUrl}/oauth/token`,
  redirectUri: "http://localhost/notfound", // no need to set up a server here, will not be called
  clientId,
  clientSecret
})
const token = await oauth
  .createToken(accessToken, refreshToken, tokenType, {})
  .refresh()
  .then(t => t.accessToken)

It’s fairly easy to find client ID, secret and UAA url, they’re in the service key of the service you are trying to access to (my abap trial shared instance in this case), but I wanted to find it programmatically, just in case one day I decided hat UX is important and code a connection wizard…

For now must be done manually:

{
  "abapfs.remote": {
    "hanatrial": {
      "url": "from_servicekey-url",
      "username": "from_eclipse",
      "password": "",
      "client": "100",
      "oauth": {
        "clientId": "from_servicekey-uaa-clientId",
        "clientSecret": "from_servicekey-uaa-clientSecret",
        "loginUrl": "from_servicekey-uaa-url",
        "saveCredentials": true
      }
    }
  }
}

This was a bit harder to figure out.

const headers = { Accept: "application/json" }
// get the list of available services
const sr = await got( "https://api.cf.eu10.hana.ondemand.com/v2/services",{ headers ,responseType: 'json'})
const services = sr.body
// get the endpoint configuration, to extract the login service URL
const resp = await got("https://api.cf.eu10.hana.ondemand.com", { headers ,responseType: 'json'})
const loginUrl = resp.body.links.login.href
// finally get the CF login token 
const token = new ClientOAuth2({ accessTokenUri: `${loginUrl}/oauth/token` })

… and then use the bearer token extracted to get:

  • organisations (`${endpoint}/v2/organizations`)
  • spaces in an organisation (`${endpoint}${organization.spaces_url}`)
  • service instances in a space `${endpoint}${space.service_instances_url}`

To figure out what service instance you’re interested on, you have lo look it up in the list of services, and then look up its guid in the service instances. Finally you can use that to get your service key:

const findAbapTag = (tags: string[]) => tags && tags.find(t => t === "abapcp")
// find the service
const abapService = services.find(s => findAbapTag(s.entity.tags))
// find the first service instance
const abapServiceInstance = instances.find(
  i => i.entity.service_guid === abapService?.metadata.guid
)


const headers = {
    Authorization: `bearer ${token..accessToken}`,
    Accept: "application/json"
}

const resp = await const resp = await got(`https://api.cf.eu10.hana.ondemand.com${abapServiceInstance.service_keys_url}`, {
    headers,
    searchParams: { q: `name:SAP_ADT` }, // Eclipse's. Should better use another
    responseType: 'json'
  })
const key =resp.body.data

 

Finally, since cloud trial allows abapgit commits, I decided it was time to add those to the client 🙂

 

DJ Adams showed how to do most of this from the command line right after I did my own homework…

/
2 Comments
You must be Logged on to comment or reply to a post.