Uniface User Forum

 View Only
  • 1.  How do I get an access token from ADFS via a web call?

    PARTNER
    Posted 06-26-2024 04:59

    I would like to call a secured web service with Uniface. To do this, I first have to call up an access token in ADFS (Active Directory Federation Services) using a user, a password and a ClientId for a client. Can anyone tell me how this is implemented in Uniface?

    What I know:

    HTTP address of the ADFS
    ClientId of the web service
    user
    password



    ------------------------------
    Viktor Künstler
    Abrechnungszentrum Emmendingen
    Emmendingen DE
    ------------------------------


  • 2.  RE: How do I get an access token from ADFS via a web call?

    Posted 07-01-2024 14:46

    Hello Viktor,

    I have tried to creating something simular for a webservice call SomToday. I was able to get the access token. The project was and is still work in progress. Only I did not continue to complete the whole program. The following operations I used for handling the request of the access token. I hope it is self-explanatory and you get a good push in the right direction with this. (Sorry for the Dutch, it's a private project.)

    Component "SOMTODAY"

      operation Inloggen   Logging in to the application, with some checking for refreshing the token

      operation getAuth  Handling the request for getting the token

      operation auth_refresh  Handling the request for refreshing the token

      Defines   The used defines

    Component "ST_WEBHANDLING"

      operation  send    Handling the request and response with the Uniface UHTTP component.

    "SOMTODAY" operation Inloggen

    ;-----------------------------------------------------------------------------------------------------------
    ; Inloggen
    ;
    ; activate "SOMTODAY".Inloggen(school_uuidIN, leerling_nummerIN, wachtwoordIN, outParamsOUT)
    ;-----------------------------------------------------------------------------------------------------------
    ; Inloggen op SomToday. 
    ;
    ; parameters:
    ;    input:     school_uuid         Te verzenden bericht, het request
    ;               leerling_nummer     Login naam om te kunnen inloggen bij SomToday
    ;               wachtwoord          Wachtwoord behorende bij het leerling_nummer
    ;    output:    outParams           Lijst met output parameters, onder andere:
    ;                 message             Melding
    ;-----------------------------------------------------------------------------------------------------------
    public operation Inloggen
    params
      string    school_uuid      : IN
      string    leerling_nummer  : IN
      string    wachtwoord       : IN
      string    outParams        : OUT
    endparams
      outParams = ""
      if (school_uuid = "" | leerling_nummer = "" | wachtwoord = ""  )
        $auth_time$ = 0
        $bError$ = <true>
        putitem/id outParams, "message", "fout inloggen, check je gegevens!"
        putmess "fout inloggen, check je gegevens!"
        return -1
      endif
    putmess "tijdstip  : %%$datim%%%"
    putmess "auth_time : %%$auth_time$%%%"
    putmess "verschil  : %%(($datim - $auth_time$)*86400)%%%"
    
      if ($bError$ = <true> | (($datim - $auth_time$)*86400) > 3060)
    ;    if (school_uuid = "")
    ;      $auth_time$ = 0
    ;      putitem/id outParams, "message", "fout inloggen, check je gegevens!"
    ;      putmess "fout inloggen, check je gegevens!"
    ;    endif
    
        activate "%%$instancename%%%".getAuth(school_uuid, leerling_nummer, wachtwoord)
        if ($access_token$ = "")
          $auth_time$ = 0
          $bError$ = <true>
          putitem/id outParams, "message", "fout inloggen, check je gegevens!"
          putmess "fout inloggen, check je gegevens!"
          return -2
        endif
        $auth_time$ = $datim
        $bError$ = <false>
    
      elseif ($auth_time$ != 0.0 & (($datim - $auth_time$)*86400) > 3000)
        if ($refresh_token$ != "")
          activate "%%$instancename%%%".auth_refresh($refresh_token$)
          if ($refresh_token$ = "" | $bError$ = <true>)
            $bError$ = <true>
            putitem/id outParams, "message", "fout inloggen, check je gegevens!"
            putmess "fout inloggen, check je gegevens!"
            return -3
          endif
          $auth_time$ = $datim
    	endif
      elseif ($bError$ = <true> | $auth_time$ = 0.0)
     ;   if (school_uuid = "")
     ;     $auth_time$ = 0
     ;     putitem/id outParams, "message", "fout inloggen, check je gegevens!"
     ;     putmess "fout inloggen, check je gegevens!"
     ;   endif
    
        activate "%%$instancename%%%".getAuth(leerling_nummer, wachtwoord, school_uuid)
        if ($access_token$ = "")
          $auth_time$ = 0
    	  $bError$ = <true>
          putitem/id outParams, "message", "fout inloggen, check je gegevens!"
          putmess "fout inloggen, check je gegevens!"
          return -4
        endif
        $auth_time$ = $datim
        $bError$ = <false>
    
      endif
    
    end  ;  operation Inloggen
    

    Component "SOMTODAY" operation getAuth

    operation getAuth
    params
      string    school_uuid     : IN
      string    leerling_nummer : IN
      string    wachtwoord      : IN
    endparams
    variables
      string    sData
      struct    strData
      numeric   vn_status
      xmlstream vx_respons
      string    vl_http_params, vs_http_status, vl_http_header, vs_melding
    endvariables
    
    
    ;https://somtoday.nl/oauth2/authorize
    ;?redirect_uri=somtodayleerling://oauth/callback
    ;&client_id=D50E0C06-32D1-4B41-A137-A9A850C892C2
    ;&response_type=code
    ;&prompt=login
    ;&scope=openid
    ;&code_challenge=tCqjy6FPb1kdOfvSa43D8a7j8FLDmKFCAz8EdRGdtQA
    ;&code_challenge_method=S256
    ;&tenant_uuid={TENANT_UUID}
    ;&oidc_iss={OIDC_ISS}".toString();
    
    
      sData = "https://inloggen.somtoday.nl/oauth2/authorize" 
      sData = $concat(sData, "?", "redirect_uri=", "somtodayleerling://oauth/callback")
      sData = $concat(sData, "&", "client_id=<client_id>")
      sData = $concat(sData, "&", "response_type=", "code")
      sData = $concat(sData, "&", "scope=", "openid")
      sData = $concat(sData, "&", "prompt=", "login")
      sData = $concat(sData, "&", "code_challenge=", "tCqjy6FPb1kdOfvSa43D8a7j8FLDmKFCAz8EdRGdtQA")
      sData = $concat(sData, "&", "code_challenge_method=", "S256")
      sData = $concat(sData, "&", "tenant_uuid=", "%%school_uuid%%%")
      sData = $concat(sData, "&", "oidc_iss=", "https://idpcluster.stichtingcarmelcollege.nl/nidp/oauth/nam")
    
      putitem/id vl_http_params, "URL", sData
      putitem/id vl_http_params, "CONTENTTYPE", "application/x-www-form-urlencoded"
      putitem/id vl_http_params, "CHARSET", "UTF-8"
      putitem/id vl_http_params, "TIMEOUT", 10000
      putitem/id vl_http_params, "HTTPS", 1
      ;putitem/id vl_http_params, "METHOD", "POST"
    
    ;  putitem/id vl_http_params, "URL", "<URL_base>/oauth2/token"
    ;  putitem/id vl_http_params, "CONTENTTYPE", "application/x-www-form-urlencoded"
    ;  putitem/id vl_http_params, "CHARSET", "UTF-8"
    ;  putitem/id vl_http_params, "TIMEOUT", 10000
    ;  putitem/id vl_http_params, "HTTPS", 1
    ;  putitem/id vl_http_params, "METHOD", "POST"
    ;
    ;  sData = "grant_type=password" 
    ;  sData = $concat(sData, "&", "username=", "%%school_uuid%%%\%%leerling_nummer%%%")
    ;  sData = $concat(sData, "&", "password=", "%%wachtwoord%%%")
    ;  sData = $concat(sData, "&", "response_type=", "code")
    ;  sData = $concat(sData, "&", "scope=", "openid")
    ;  sData = $concat(sData, "&", "tenant_uuid=", "%%school_uuid%%%")
    ;  sData = $concat(sData, "&", "client_id=<client_id>")
    ;  sData = $concat(sData, "&", "redirect_uri=", "somtodayouder%3A%2F%2Foauth%2Fcallback")
    ;  sData = $concat(sData, "&", "session=", "no_session")
    ;  sData = $concat(sData, "&", "oidc_iss=", "https://idpcluster.stichtingcarmelcollege.nl/nidp/oauth/nam")
    ;; redirect_uri 	Query 	somtodayleerling://oauth/callback
    ;; client_id 	Query 	D50E0C06-32D1-4B41-A137-A9A850C892C2
    ;; response_type 	Query 	code
    ;; scope 	Query 	openid
    ;; tenant_uuid 	Query 	[SCHOOL UUID]
    ;; session 	Query 	no_session
    ;; state 	Query 	[RANDOM STATE]
    ;; code_challenge 	Query 	[CODE CHALLENGE]
    ;; code_challenge_method 	Query 	S256
    
    putmess sData
      activate "ST_WEBHANDLING".send(sData, vl_http_params, vs_http_status, vl_http_header, vx_respons, vn_status, vs_melding)
    
    ; fileload "project\auth.json", vx_respons
    
      putmess "HTTPSTATUS         : %%vs_http_status%%%"
      putmess "RESPONS            : %%vx_respons%%%"
      putmess "HTTPHEADER         : %%$item("REQUEST", vl_http_header)%%%"
      putmess "HTTPHEADER_RESPONS : %%$item("RESPONS", vl_http_header)%%%"
    
      jsonToStruct strData, vx_respons
    
      $access_token$ = strData->"access_token"
      $refresh_token$ = strData->"refresh_token"
      putitem/id $access_header$, "Authorization", "Bearer %%$access_token$%%%"
      putitem/id $access_header$, "Accept", "application/json"
      $somtoday_api_url$ = strData->"somtoday_api_url"
      $somtoday_tenant$ = strData->"somtoday_tenant"
      $id_token$ = strData->"id_token"
      $auth_expires_in$ = strData->"expires_in"
    
    end  ;  operation getAuth
    

    Component "SOMTODAY" operation auth_refresh

    operation auth_refresh
    params
      string    refresh_token  : IN
    endparams
    variables
      string    sData
      struct    strData
      numeric   vn_status
      xmlstream vx_respons
      string    vl_http_params, vs_http_status, vl_http_header, vs_melding
    endvariables
    
      putitem/id vl_http_params, "URL", "<URL_base>/oauth2/token"
      putitem/id vl_http_params, "CONTENTTYPE", "application/x-www-form-urlencoded"
      putitem/id vl_http_params, "CHARSET", "UTF-8"
      putitem/id vl_http_params, "TIMEOUT", 10000
      putitem/id vl_http_params, "HTTPS", 1
      putitem/id vl_http_params, "METHOD", "POST"
    
      sData = "grant_type=refresh_token" 
      sData = $concat(sData, "&", "refresh_token=", "%%refresh_token%%%")
      sData = $concat(sData, "&", "client_id=<client_id>")
    
      activate "ST_WEBHANDLING".send(sData, vl_http_params, vs_http_status, vl_http_header, vx_respons, vn_status, vs_melding)
    
      putmess "HTTPSTATUS         : %%vs_http_status%%%"
      putmess "RESPONS            : %%vx_respons%%%"
      putmess "HTTPHEADER         : %%$item("REQUEST", vl_http_header)%%%"
      putmess "HTTPHEADER_RESPONS : %%$item("RESPONS", vl_http_header)%%%"
    
    putmess vx_respons
      jsonToStruct strData, vx_respons
    
      putmess strData->$dbgString
    
      $access_token$ = strData->"access_token"
      $refresh_token$ = strData->"refresh_token"
      putitem/id $access_header$, "Authorization", "Bearer %%$access_token$%%%"
      putitem/id $access_header$, "Accept", "application/json"
      $somtoday_api_url$ = strData->"somtoday_api_url"
    
    putmess $access_token$
    putmess $refresh_token$
    putmess $access_header$
    putmess $somtoday_api_url$
    
    
    end  ;  operation auth_refresh
    

    Component "ST_WEBHANDLING" operation send

    ;-----------------------------------------------------------------------------------------------------------
    ; SEND
    ;
    ; activate send(requestIN, paramsIN, HTTPstatusOUT, HTTPheaderOUT, responsOUT, statusOUT, contextOUT)
    ;-----------------------------------------------------------------------------------------------------------
    ; Verzend een bericht via HTTP. 
    ;
    ; parameters:
    ;    input:     px_request          Te verzenden bericht, het request
    ;               pl_params           Params gecombineerd in een lijst. Waaronder:
    ;                 url                 Endpoint    
    ;                 https               Verzenden via HTTPS?
    ;                 timeout             Timeout van het verzonden bericht, leeg = geen timeout
    ;                 username            Username om van HTTP Authentication gebruik te maken
    ;                 password            Password behorende bij de username
    ;                 soapaction          De SOAPACTION in de httpheader
    ;                 contenttype         De contenttype in de httpheader
    ;                 charset             Charset van de request
    ;                 Authorization       Authorization
    ;                 Accept              Accept
    ;                 method              Gebruikte HTTP method (GET of POST)
    ;    output:    pn_http_status      HTTP status van de verzending, onder andere:
    ;                                        0 = bericht hoogst waarschijnlijk niet verzonden
    ;                                      200 = bericht is goed ontvangen door de wederpartij. Px_respons bevat antwoord.
    ;                                      404 = URL is niet correct, wederpartij niet gevonden
    ;                                      500 = Ontvanger heeft fout in bericht geconstateerd. Px_respons bevat fout.
    ;               pl_http_header      HTTP header
    ;               px_respons          Antwoord zoals ontvangen van de wederpartij.
    ;               pn_status           Status van de verwerking. Onder andere:
    ;                                        0 = Verwerking goed verlopen. HTTP status = 200!
    ;                                        1 = Verwerking goed verlopen. HTTP status geeft echter fout!!
    ;                                       -1 = onbekende fout bij verzending
    ;                                      -10 = URL niet goed 
    ;                                      -11 = Timeout
    ;                                      -12 = Timeout
    ;                                      -13 = Request niet goed
    ;               pl_status_context   Context van de status.
    ;-----------------------------------------------------------------------------------------------------------
    public operation send
    params
      xmlstream px_request :IN
      string    pl_params : IN
      numeric   pn_http_status : OUT
      string    pl_http_header : OUT
      xmlstream px_respons : OUT
      numeric   pn_status : OUT
      string    pl_status_context : OUT
    endparams
    variables
      string    vs_headers, strInstance, vs_respons_header, vs_url
      string    vs_username, vs_password, vs_contenttype, vs_soapaction
      string    vs_authorization, vs_accept
      string    vs_method, vl_http_header, vs_charset, v_tmp
      boolean   vb_https
      xmlstream vx_content_part, vx_content
      numeric   vn_chunk_size, vn_poging, vn_timeout, vn_flag, vn_status_send
      string    vs_starttijd, vs_eindtijd
      numeric   vn_starttijd, vn_eindtijd, vn_doorlooptijd
    
    endvariables
       
      pn_status = 0
      pn_http_status = 0
      vn_chunk_size = 1000000
       
      getitem/id vs_url, pl_params, "URL"
      getitem/id vs_username, pl_params, "USERNAME"
      if (vs_username !="")
        vs_username = "%%vs_username%%%(scheme=B)"
      endif
      getitem/id vs_password, pl_params, "PASSWORD"
      getitem/id vs_contenttype, pl_params, "CONTENTTYPE"
      getitem/id vs_charset, pl_params, "CHARSET"
      getitem/id vs_soapaction, pl_params, "SOAPACTION"
      getitem/id vn_timeout, pl_params, "TIMEOUT"
      getitem/id vs_method, pl_params, "METHOD"
      if (vs_method = "")
         vs_method = "GET"
      endif
      getitem/id vb_https, pl_params, "HTTPS"
      getitem/id vs_authorization, pl_params, "Authorization"
      getitem/id vs_accept, pl_params, "Accept"
    
      strInstance = "UHTTP"
      newinstance "UHTTP", strInstance
       
      ; Set flags vraagt om bits 1, 2 of 3. Dus niet de waarde.
      ; 001 = 1    errors caused by certificate host names that do not match request host names are ignored
      ; 010 = 2    errors caused by expired server certificates are ignored
      ; 100 = 4    the SEND method does not calculate the content-length of the payload itself for a POST method
      ; Om https te kunnen verzenden zijn bits 2 en 3 nodig, dus 2+4=6
      if (vb_https)
        vn_flag = 30
        activate strInstance.set_flags(vn_flag)
      endif
    
      if (vn_timeout > 0)
        ; timeout in milliseconden.
        if (vn_timeout > 0 & vn_timeout < 100) 
          ; Kleiner dan een tiende seconde? Waarschijnlijk is timeout in seconden opgegeven
          vn_timeout = vn_timeout * 1000
        endif
      else
        vn_timeout = -1
      endif
    
      activate strInstance.set_timeout(vn_timeout)
      if ($status <0)
        pn_status = $procerror
        pl_status_context = $procerrorcontext
      endif
       
      vx_content = px_request
    
      ; is het bericht langer dan de chunksize, dan eerst het bericht in stukken aanbieden aan de uhttp component
      length vx_content
      while ($result > vn_chunk_size)
           
        activate "UHTTP".WRITE_CONTENT(vx_content[1:vn_chunk_size])
           
        vx_content = vx_content[vn_chunk_size+1]
        length vx_content
      endwhile
    
      if (vs_contenttype != "")
        putitem/id vl_http_header, "Content-Type", "%%vs_contenttype%%%"
      else
        putitem/id vl_http_header, "Content-Type", "text/xml"
      endif
      if (vs_soapaction != "")
        putitem/id vl_http_header, "SOAPAction", vs_soapaction
      endif
      putitem/id vl_http_header, "charset", vs_charset
      if (vs_authorization != "")
        putitem/id vl_http_header, "Authorization", vs_authorization
      endif
      if (vs_accept != "")
        putitem/id vl_http_header, "Accept", vs_accept
      endif
    
      vn_poging = 0
      repeat
        vn_poging = vn_poging + 1
    
        putitem/id pl_http_header, "REQUEST", vl_http_header 
    
    ;    activate strInstance.send(vs_url, "POST"   , vs_username, vs_password, vl_http_header, vx_content, vs_respons_header)
        activate strInstance.send(vs_url, vs_method, vs_username, vs_password, vl_http_header, vx_content, vs_respons_header)
        pn_http_status = $status
        vn_status_send = $status
        putitem/id pl_http_header, "RESPONS", vl_http_header 
        $status = vn_status_send
      until (vn_poging > 2 | $status != -11)
    
      while ($status = 1)
        activate strInstance.read_content(vx_content_part)
        vx_content = $concat(vx_content, vx_content_part)
      endwhile
    
      px_respons = vx_content
    
      if (vx_content != "")
        px_respons = vx_content
      else
        px_respons = vs_respons_header
      endif
    
      selectcase pn_http_status
        case 0
          ; Bericht is niet verzonden
          pn_status = -1
          putitem/id pl_status_context, "DESCRIPTION", "Bericht is niet verzonden wegens een onbekende fout"
          putitem/id pl_status_context, "COMPONENT", $componentname
        case -10
          ; URL is niet correct
          pn_status = -10
          putitem/id pl_status_context, "DESCRIPTION", "URL is niet correct"
          putitem/id pl_status_context, "COMPONENT", $componentname
        case -11
          ; Timeout van UHTTP component. 
          pn_status = -11
          putitem/id pl_status_context, "DESCRIPTION", "Timeout (%%vn_poging%%% pogingen)"
          putitem/id pl_status_context, "COMPONENT", $componentname
        case -12
          ; INterne fout van UHTTP component. Treedt ook op bij timeout, ga hiervanuit.....
          pn_status = -12
          putitem/id pl_status_context, "DESCRIPTION", "Timeout"
          putitem/id pl_status_context, "COMPONENT", $componentname
        case -13
          ; request is niet correct
          pn_status = -13
          putitem/id pl_status_context, "DESCRIPTION", "Request is niet correct"
          putitem/id pl_status_context, "COMPONENT", $componentname
        case 200
          pn_status = 0
          putitem/id pl_status_context, "DESCRIPTION", "Bericht is verzonden."
          putitem/id pl_status_context, "COMPONENT", $componentname
        elsecase
          ;if ($status > 0)
          if (pn_http_status > 0) ; http status
            pn_status = 1
            putitem/id pl_status_context, "COMPONENT", $componentname
            putitem/id pl_status_context, "DESCRIPTION", vs_respons_header
          else
            pn_status = $procerror
            pl_status_context = $procerrorcontext
          endif
      endselectcase
    
    end ; send
    

    Component "SOMTODAY" Defines:

    ; Your component defines here (optional)...
    #define client_id D50E0C06-32D1-4B41-A137-A9A850C892C2
    #define true  1
    #define false 0
    
    #define URL_base https://somtoday.nl
    #define URL_organisaties  https://servers.somtoday.nl/organisaties.json
    
    ; Your component VARIABLES block here (optional)...
    variables
      string    student_id
      string    school_uuid
      string    access_token
      string    refresh_token
      string    access_header
      string    stand_header
      datetime  auth_time
      boolean   bError
    
      string    somtoday_api_url
      string    somtoday_oop_url
      string    auth_scope
      string    somtoday_tenant
      string    id_token
      string    token_type
      string    auth_expires_in
    
      date     DIS(yyyy-mm-dd) dtDateyyyymmdd
    
    endvariables

    Greetings,



    ------------------------------
    Richard de Vries
    Sogeti Nederland B.V.
    NL
    ------------------------------



  • 3.  RE: How do I get an access token from ADFS via a web call?

    PARTNER
    Posted 07-02-2024 00:46
    Edited by Private Private 07-02-2024 00:46

    Thank you Richard for your detailed answer.



    ------------------------------
    Viktor Künstler
    Abrechnungszentrum Emmendingen
    Emmendingen DE
    ------------------------------