No arquivo appserver.ini inclua as configurações necessárias como mostra o passo a passo no link abaixo:
Configuração rest protheus
Para a autenticação oAuth funcionar é necessário configurar o servidor rest com https, para isso na seção HTTPREST (conforme link acima) precisa estar configurado da seguinte forma:
[HTTPREST] Port=8090 URIs=HTTPURI Security=1 SSL2=0 SSL3=1 CERTIFICATE =C:\TOTVS\totvs_harpia\Protheus\bin\appserver\totvs_certificate.crt KEY =C:\TOTVS\totvs_harpia\Protheus\bin\appserver\totvs_certificate_key.pem TLS1 =3 |
Em um ambiente de produção o certificado utilizado precisa ser um certificado valido e emitido por uma empresa autenticadora reconhecida. |
Para a autenticação via oAuth é necessário gerar as chaves publica e privada conforme é demonstrado no link abaixo:
Gerando as chaves oAuth no configurador
Exemplo de um fonte advpl consumindo uma api rest do protheus e autenticando via oAuth:
#include "protheus.ch" #include "rwmake.ch" //------------------------------------------------------------------- /*/{Protheus.doc} OAuthT1 Teste oAuth, consumo manual @author Caio Lima @since 14/06/2022 //-----------------------------------------------------------------*/ User Function OAuthT1() Local oUrl as object Local oOauth as object Local cUrlBase as character Local cUrlReq as character Local cUrlAut as character Local cUrlAcc as character Local cConsumerKey as character Local cConsumerSecret as character Local oJsonRet as object cConsumerKey := "155dfkjh2uhi1uh237y1231sdfad20f093fc" cConsumerSecret := "b090cf3asdfsaf123dafjh2u1291c6f8328" cUrlBase := "https://localhost:8090/rest" cUrlReq := cUrlBase + "/oAuth/Request_Token" cUrlAut := cUrlBase + "/oAuth/Login" cUrlAcc := cUrlBase + "/oAuth/Access_Token" oUrl := FWoAuthURL():New(cUrlReq, cUrlAut, cUrlAcc) oOauth := MyoAuthClient():New( cConsumerKey, cConsumerSecret, oUrl, /* cCallBack */ "" ) oOauth:SetMethodSignature("PLAINTEXT") oOauth:SetUser("admin","1234") oOauth:SetContentType("application/json") cReturn := oOauth:Get(cUrlBase + "/shiftf6/",,,) If !Empty(cReturn) oJsonRet := JsonObject():New() oJsonRet:FromJSON(cReturn) Aviso( 'VarInfo', VarInfo('oJsonRet', oJsonRet , , .F. ) ,{'ok'} ,4,,,, .T.) EndIf Return //------------------------------------------------------------------- /*/{Protheus.doc} MyoAuthClient Classe para conexão com cliente oAuth com assinatura plaintext @author Caio Lima @since 14/06/2022 //-----------------------------------------------------------------*/ Class MyoAuthClient From FWoAuthClient Data cUser as character Data cPassword as character Data aLastError as array // token definitivo Data cDefToken as character Data cDefTokenSecret as character Method New() CONSTRUCTOR Method UpdateParam() Method SetUser() Method Authorize() Method AccessToken() Method GetOAuthHeader() Method Get() EndClass //------------------------------------------------------------------- /*/{Protheus.doc} setUser define usuario e senha @author Caio Lima @since 14/06/2022 //-----------------------------------------------------------------*/ Method SetUser(cUser, cPassword) CLASS MyoAuthClient self:cUser := cUser self:cPassword := cPassword Return //------------------------------------------------------------------- /*/{Protheus.doc} New Metodo construtor @author Caio Lima @since 14/06/2022 //-----------------------------------------------------------------*/ Method New(cConsumer,cSecret,oURL,cCallback) CLASS MyoAuthClient _Super:New(cConsumer,cSecret,oURL,cCallback) Return self //------------------------------------------------------------------- /*/{Protheus.doc} Get GET @author Caio Lima @since 15/06/2022 //-----------------------------------------------------------------*/ Method Get(cUrl) CLASS MyoAuthClient Local aHeader as array Local cRet as character Local cHeadRet as character self:RequestToken() If self:Authorize() If self:AccessToken() self:UpdateParam(.T.) aHeader := self:GetOAuthHeader() cRet := HttpGet(cUrl, "",120, aHeader, @cHeadRet) If !"200 OK" $ cHeadRet .OR. Empty(cRet) self:aLastError := {cHeadRet, cRet} Aviso( 'Method Get', VarInfo('aLastError', self:aLastError , , .F. ) ,{'ok'} ,4,,,, .T.) EndIf EndIf EndIf Return(cRet) //------------------------------------------------------------------- /*/{Protheus.doc} GetOAuthHeader retorna o header com Authorization:OAuth conforme self:parametros @author Caio Lima @since 15/06/2022 //-----------------------------------------------------------------*/ Method GetOAuthHeader() CLASS MyoAuthClient Local cHeadAut as character Local aHeader as array Local _nx as numeric aHeader := {} cHeadAut := "Authorization:OAuth " For _nx := 1 to Len(self:aParametros) cHeadAut += self:aParametros[_nx,1] + '="' + self:aParametros[_nx,2] + '" ' Next If !Empty(self:cUser) cHeadAut += 'user="'+ self:cUser +'" password="'+ self:cPassword +'"' Else // retira a virgula final cHeadAut := Left(cHeadAut, Len(cHeadAut) - 1) EndIf Aadd(aHeader, cHeadAut) Return(aHeader) //------------------------------------------------------------------- /*/{Protheus.doc} AccessToken Define o token definitivo de acesso que já pode ser utilizado no consumo das apis @author Caio Lima @since 14/06/2022 //-----------------------------------------------------------------*/ Method AccessToken(ntipo) Class MyoAuthClient Local cHeadRet as character Local aRet as array Local lRet as logical cHeadRet := "" self:UpdateParam() cRet := HttpGet(self:oURL:cAccess, "",120, self:GetOAuthHeader(), @cHeadRet) If "200 OK" $ cHeadRet .AND. "oauth_token_secret" $ cRet cRet := StrTran(cRet, "oauth_token=", "") cRet := StrTran(cRet, "oauth_token_secret=", "") aRet := StrTokArr(cRet,"&") self:cDefToken := aRet[1] self:cDefTokenSecret := aRet[2] lRet := .T. Else lRet := .F. self:aLastError := {cHeadRet, cRet} Aviso( 'Method AccessToken', VarInfo('aLastError', self:aLastError , , .F. ) ,{'ok'} ,4,,,, .T.) EndIf Return(lRet) //------------------------------------------------------------------- /*/{Protheus.doc} Authorize Efetua a autenticação do usuario no server @author Caio Lima @since 15/06/2022 //-----------------------------------------------------------------*/ Method Authorize() Class MyoAuthClient Local lRet as logical Local cHeadRet as character lRet := .F. cHeadRet := "" self:UpdateParam() cRet := HttpGet(self:oURL:cAuthorize, "",120,self:GetOAuthHeader(), @cHeadRet) If "200 OK" $ cHeadRet .AND. "<error>0</error>" $ Lower(cRet) lRet := .T. Else lRet := .F. self:aLastError := {cHeadRet, cRet} Aviso( 'Method Authorize', VarInfo('aLastError', self:aLastError , , .F. ) ,{'ok'} ,4,,,, .T.) EndIf Return(lRet) //------------------------------------------------------------------- /*/{Protheus.doc} UpdateParam Atualiza parâmetros do oAuth @author Caio Lima @since 15/06/2022 /*/ //------------------------------------------------------------------- Method UpdateParam(lDefToken) CLASS MyoAuthClient Default lDefToken := .F. self:aParametros := {} self:cNonce := SubStr(Sha1(DToS(Date()) + Time()),1,32) self:cTimeStamp := FWTimeStamp(4) aAdd(self:aParametros,{"oauth_consumer_key",Escape(self:cConsumerKey)}) aAdd(self:aParametros,{"oauth_timestamp",self:cTimeStamp}) aAdd(self:aParametros,{"oauth_nonce",self:cNonce}) aAdd(self:aParametros,{"oauth_signature_method","PLAINTEXT"}) aAdd(self:aParametros,{"oauth_version","1.0"}) aAdd(self:aParametros,{"oauth_signature", self:cSecretKey + Iif(Empty(self:cSecretToken),"","&" + self:cSecretToken) }) If lDefToken aAdd(self:aParametros,{"oauth_token",self:cDefToken}) aAdd(self:aParametros,{"oauth_token_secret",self:cDefTokenSecret}) ElseIf !Empty(self:cToken) aAdd(self:aParametros,{"oauth_token",self:cToken}) aAdd(self:aParametros,{"oauth_token_secret",self:cSecretToken}) EndIf Return self |
Após configurado o rest e gerado as chaves de autenticação,
basta alterar as variáveis cConsumerKey e cConsumerSecret da função acima e corrigir o endereço na cUrlBase.
Depois é só chamar a função U_OAuthT1()