Article
· Fév 27 4m de lecture

Utilisation d'Oauth2 avec les services (Web) SOAP

Salut les gars,

Il y a quelques jours, un client m'a contacté avec le souhait d'améliorer son application existante, qui utilise les services SOAP afin de partager la même autorisation avec sa nouvelle API d'application basée sur REST. Comme leur nouvelle application utilise OAuth2, le défi était clair : comment transmettre le token d'accès avec la requête SOAP au serveur.

Après avoir passé du temps sur Google, il s'est avéré que l'un des moyens possibles d'y parvenir consistait à ajouter un élément d'en-tête supplémentaire à l'enveloppe SOAP, puis à s'assurer que l'implémentation du WebService fait ce qui est nécessaire pour valider le jeton d'accèsю

 

Heureusement, nous disposons d'un mécanisme qui permet de fournir des headers personnalisés avec une requête SOAP. J'ai donc simplement suivi la documentation – voir ici pour plus de détails – et j'ai sorti les cours suivants.

La classe personnalisée

Class API.SOAP.OAuth2Header Extends %SOAP.Header
{

Property accessToken As %String(MAXLEN = "");

}

Très simple, en effet. Tout ce dont j'ai besoin est de transmettre le token d'accès, mais il peut être étendu pour transmettre d'autres informations.

La classe d'implémentation du service Web

/// API.SOAP.MyService
Class API.SOAP.MyService Extends %SOAP.WebService [ ProcedureBlock ]
{

/// Nom du WebService.
Parameter SERVICENAME = "MyService";

/// TODO : remplacez-le par l'espace de noms SOAP réel.
/// Espace de noms SOAP pour le WebService
Parameter NAMESPACE = "http://tempuri.org";

/// Les espaces de noms des classes référencées seront utilisés dans le WSDL.
Parameter USECLASSNAMESPACES = 1;

/// TODO : ajoutez d'arguments et implémentation.
/// GetVersion
Method GetAccountBalance(pAccNo As %String) As API.SOAP.DT.Account [ WebMethod ]

{
  #define APP       "ANG RESOURCES"
  try {
    #dim tAccessTokenHeader as API.SOAP.OAuth2Header=..HeadersIn.GetAt("OAuth2Header")

    $$$THROWONERROR(tSC,##class(%SYS.OAuth2.AccessToken).GetIntrospection($$$APP,tAccessTokenHeader.accessToken,.jsonObjectAT))

    /* vérification spécifique au service */
    // vérifie si la requête demande une portée appropriée pour ce service
    if '(jsonObjectAT.scope["account") set reason="scope not supported" throw 
        
    if '(##class(%SYS.OAuth2.Validation).ValidateJWT($$$APP,tAccessTokenHeader.accessToken,,,.jsonObjectJWT,.securityParameters,.tSC)) {
      set reason="unauthorized access attempt"
      throw
    }           
    set tAccountObject=##class(API.SOAP.DT.Account).%New()
    set tAccountObject.accno=pAccNo
    set tAccountObject.owner=jsonObjectJWT."acc-owner"
    set tAccountObject.balance=$random(200000)
  } catch (e) {
    set fault=..MakeFault($$$FAULTServer,"SECURITY",reason)
    Do ..ReturnFault(fault)
  }
  Quit tAccountObject
}

XData AdditionalHeaders

{
<parameters xmlns="http://www.intersystems.com/configuration">
<request>
<header name="OAuth2Header" class="API.SOAP.OAuth2Header"/> 
</request>
</parameters>
}
}

Passons quelques mots sur la vérification du token d'accès. Comme vous pouvez le voir, la toute première tâche que nous effectuons consiste à récupérer le token d'accès de header personnalisé et à le désérialiser en une représentation d'objet.

Ensuite, c'est à nous de vérifier la portée ou d'effectuer d'autres validations, comme la validation du token JWT (cela dépend de la façon dont nous avons configuré le serveur d'autorisation OAuth2 et si nous utilisons OpenID, ce que je recommande vivement !)

 

Jetons maintenant un coup d'œil du côté client.

Je n'expliquerai pas en détail comment votre client reçoit le token d'accès pour votre serveur d'autorisation Oauth2, pour cela vous pouvez voir mes autres articles ; au lieu de cela, nous regardons simplement comment nous fournissons le token d'accès à un client de service Web. (Vous générez une ou plusieurs classes client WebService en exécutant l'option SOAP Wizard / Client standard à partir de votre IDE Atelier ou Studio).

Voici l'extrait de code de mon client

 

  set tWSClient=##class(Web.WSC.MyServiceSoap).%New()
  set tWSHeader=##class(Web.WSC.s0.OAuth2Header).%New()

  set tWSHeader.accessToken=accessToken
  do tWSClient.HeadersOut.SetAt(tWSHeader,"access-token")
  #dim tAccountObject as Web.WSC.s0.Account=tWSClient.GetAccountBalance(tAccNo)

Considérations sur la configuration de la sécurité sur le serveur de ressources

Le plus simple, mais risqué, consistait à configurer votre application CSP sur le serveur de ressources (WebServer) et à lui permettre d'autoriser les utilisateurs non authentifiés. Eux, c'est toujours à vous d'enregistrer chaque service et chaque méthode de token d'accès et de le valider. Si aucun token d’accès n’est présent ou n’est pas valide, vous DEVEZ renvoyer SOAP Fault.

L'autre méthode, mais la meilleure, consiste à utiliser l'authentification déléguée et à demander à la routine ZAUTHENTICATE de récupérer le token d'accès, en attribuant un nom d'utilisateur délibéré (peut être extrait de JWT si le profil OpenID est fourni avec une portée dans la demande de token d'accès) avec un ensemble minimal de rôles nécessaires à l'exécution de méthode du serveur Web.

Discussion (0)1
Connectez-vous ou inscrivez-vous pour continuer