|  | (SQL Server) Datev OAuth2 Access TokenDemonstrates how to get a Datev OAuth2 access token from a desktop application or script.Note: This example requires Chilkat v10.1.3 or greater. 
 -- Important: See this note about string length limitations for strings returned by sp_OAMethod calls.
--
CREATE PROCEDURE ChilkatSample
AS
BEGIN
    DECLARE @hr int
    DECLARE @iTmp0 int
    -- Important: Do not use nvarchar(max).  See the warning about using nvarchar(max).
    DECLARE @sTmp0 nvarchar(4000)
    -- To further clarify, see OAuth 2.0 Authorization Flow
    DECLARE @oauth2 int
    EXEC @hr = sp_OACreate 'Chilkat.OAuth2', @oauth2 OUT
    IF @hr <> 0
    BEGIN
        PRINT 'Failed to create ActiveX component'
        RETURN
    END
    -- Your Datev app should use "http://localhost" (no trailing forward slash) for the redirect URL.
    EXEC sp_OASetProperty @oauth2, 'ListenPort', 3017
    --  EXEC sp_OASetProperty @oauth2, 'AuthorizationEndpoint', 'https://login.datev.de/openidsandbox/authorize'
    EXEC sp_OASetProperty @oauth2, 'TokenEndpoint', 'https://sandbox-api.datev.de/token'
    -- Replace this with your actual client ID.
    EXEC sp_OASetProperty @oauth2, 'ClientId', 'DATEV_CLIENT_ID'
    EXEC sp_OASetProperty @oauth2, 'ClientSecret', 'DATEV_CLIENT_SECRET'
    EXEC sp_OASetProperty @oauth2, 'CodeChallenge', 1
    EXEC sp_OASetProperty @oauth2, 'CodeChallengeMethod', 'S256'
    EXEC sp_OASetProperty @oauth2, 'Scope', 'openid profile email datev:accounting:clients accounting:documents datev:accounting:extf-files-import'
    -- Begin the OAuth2 authorization code flow.  This returns a URL that should be loaded in a browser.
    DECLARE @url nvarchar(4000)
    EXEC sp_OAMethod @oauth2, 'StartAuth', @url OUT
    EXEC sp_OAGetProperty @oauth2, 'LastMethodSuccess', @iTmp0 OUT
    IF @iTmp0 <> 1
      BEGIN
        EXEC sp_OAGetProperty @oauth2, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @oauth2
        RETURN
      END
    -- Launch the default browser on the system and navigate to the url.
    -- The LaunchBrowser method was added in Chilkat v10.1.2.
    DECLARE @success int
    EXEC sp_OAMethod @oauth2, 'LaunchBrowser', @success OUT, @url
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @oauth2, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @oauth2
        RETURN
      END
    -- Wait for the interactive user to grant permission in the interactive browser session.
    -- We'll wait for a max of 90 seconds.
    DECLARE @numMsWaited int
    SELECT @numMsWaited = 0
    EXEC sp_OAGetProperty @oauth2, 'AuthFlowState', @iTmp0 OUT
    WHILE (@numMsWaited < 90000) and (@iTmp0 < 3)
      BEGIN
        EXEC sp_OAMethod @oauth2, 'SleepMs', NULL, 100
        SELECT @numMsWaited = @numMsWaited + 100
      END
    -- If there was no response from the browser within 90 seconds, then 
    -- the AuthFlowState will be equal to 1 or 2.
    -- 1: Waiting for Redirect. The OAuth2 background thread is waiting to receive the redirect HTTP request from the browser.
    -- 2: Waiting for Final Response. The OAuth2 background thread is waiting for the final access token response.
    -- In that case, cancel the background task started in the call to StartAuth.
    EXEC sp_OAGetProperty @oauth2, 'AuthFlowState', @iTmp0 OUT
    IF @iTmp0 < 3
      BEGIN
        EXEC sp_OAMethod @oauth2, 'Cancel', @success OUT
        PRINT 'No response from the browser!'
        EXEC @hr = sp_OADestroy @oauth2
        RETURN
      END
    -- Check the AuthFlowState to see if authorization was granted, denied, or if some error occurred
    -- The possible AuthFlowState values are:
    -- 3: Completed with Success. The OAuth2 flow has completed, the background thread exited, and the successful JSON response is available in AccessTokenResponse property.
    -- 4: Completed with Access Denied. The OAuth2 flow has completed, the background thread exited, and the error JSON is available in AccessTokenResponse property.
    -- 5: Failed Prior to Completion. The OAuth2 flow failed to complete, the background thread exited, and the error information is available in the FailureInfo property.
    EXEC sp_OAGetProperty @oauth2, 'AuthFlowState', @iTmp0 OUT
    IF @iTmp0 = 5
      BEGIN
        PRINT 'OAuth2 failed to complete.'
        EXEC sp_OAGetProperty @oauth2, 'FailureInfo', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @oauth2
        RETURN
      END
    EXEC sp_OAGetProperty @oauth2, 'AuthFlowState', @iTmp0 OUT
    IF @iTmp0 = 4
      BEGIN
        PRINT 'OAuth2 authorization was denied.'
        EXEC sp_OAGetProperty @oauth2, 'AccessTokenResponse', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @oauth2
        RETURN
      END
    EXEC sp_OAGetProperty @oauth2, 'AuthFlowState', @iTmp0 OUT
    IF @iTmp0 <> 3
      BEGIN
        EXEC sp_OAGetProperty @oauth2, 'AuthFlowState', @iTmp0 OUT
        PRINT 'Unexpected AuthFlowState:' + @iTmp0
        EXEC @hr = sp_OADestroy @oauth2
        RETURN
      END
    -- Save the full JSON access token response to a file.
    DECLARE @sbJson int
    EXEC @hr = sp_OACreate 'Chilkat.StringBuilder', @sbJson OUT
    EXEC sp_OAGetProperty @oauth2, 'AccessTokenResponse', @sTmp0 OUT
    EXEC sp_OAMethod @sbJson, 'Append', @success OUT, @sTmp0
    EXEC sp_OAMethod @sbJson, 'WriteFile', @success OUT, 'qa_data/tokens/datev.json', 'utf-8', 0
    -- The saved JSON response looks like this:
    -- {
    -- 	"refresh_token": "ZDA5Y .... FFhTXc9",
    -- 	"refresh_token_expires_in": 39600,
    -- 	"id_token": "eyJ .... Q9w",
    -- 	"access_token": "MTM .... 1UDA9",
    -- 	"token_type": "bearer",
    -- 	"expires_in": 900		
    -- }
    PRINT 'OAuth2 authorization granted!'
    EXEC sp_OAGetProperty @oauth2, 'AccessToken', @sTmp0 OUT
    PRINT 'Access Token = ' + @sTmp0
    EXEC @hr = sp_OADestroy @oauth2
    EXEC @hr = sp_OADestroy @sbJson
END
GO |