Search code examples
perlpostmigrationmicrosoft-translator

get_access_token in perl after Microsoft Translator API migration


Microsoft DataMarket platform retired on April 30, 2017 and moved the Microsoft Translator API to Azure.

They have a full example of how to get the new token in C# here

Our old process, however, is perl which I have zero prior experience with. It grabbed the token using post in the code below :

if (!$token or time > $expire - 5) {
    $token = '';
    console_log("Getting a new access token.") if ($debug);
    my $response = $ua->post(
        "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13/",
        [
            client_id     => $clientid,
            client_secret => $clientsecret,
            scope         => 'http://api.microsofttranslator.com',
            grant_type    => 'client_credentials',
        ],
    );
    if ($response->is_success and $response->content =~ /^\{"token_type":".+?","access_token":"(.+?)","expires_in":"(\d+?)","scope":".+?"\}$/) {
        $token = uri_escape("Bearer $1");
        $expire = time + $2;
        if ($fh) {
            seek($fh, 0,0);
            print $fh "expire:$expire\n";
            print $fh "token:$token\n";
            truncate($fh, tell($fh));
        }
    } else {
        console_log("Failed to get Access Token.") if ($debug);
    }
}
close $fh if($fh);
return $token;
}

I was thinking that this could be as simple as changing to the updated url and scraping the old client_id and client secret, something like this :

my $response = $ua->post(
        "https://api.cognitive.microsoft.com/sts/v1.0/issueToken",
        [
               //Ocp-Apim-Subscription-Key => newazurekey
        ],
    );

I have two concerns though

1) The documentation sites I have found and read, one says Ocp-Apim-Subscription-Key is a header, the other a parameter is the code Ocp-Apim-Subscription-Key => newazurekey ok? does Perl allow dashes?

Documentation sites : one, two, three

2) The response recieved testing the API doesn't seem to have the token_type: access_token: expires_in: or scope: like in the old code

I'm referring to this condition

if ($response->is_success and $response->content =~ /^\{"token_type":".+?","access_token":"(.+?)","expires_in":"(\d+?)","scope":".+?"\}$/)

The response looks like this

enter image description here

Am I on the right track for grabbing the token correctly or will more changes need to be made?


Solution

  • Add

    # Sample code uses five minutes
    use constant DEFAULT_TOKEN_LIFETIME => 5 * 60;
    

    From a cursory look, the following might work:

    if (!$token or time > $expire - 5) {
        $token = '';
        console_log("Getting a new access token.") if ($debug);
        my $response = $ua->post(
            "https://api.cognitive.microsoft.com/sts/v1.0/issueToken",
            [
                'Ocp-Apim-Subscription-Key' => $newazurekey,
            ],
        );
        if ($response->is_success) {
            $token = "Bearer " . $response->decoded_content;
            $expire = time + DEFAULT_TOKEN_LIFETIME;
            if ($fh) {
                seek($fh, 0,0);
                print $fh "expire:$expire\n";
                print $fh "token:$token\n";
                truncate($fh, tell($fh));
            }
        } else {
            console_log("Failed to get Access Token.") if ($debug);
        }
    }
    close $fh if($fh);
    return $token;
    }
    

    This comment says token lifetime is ten minutes, but the code sample uses a five minute interval:

    // Use a duration of 5 minutes, which is less than the actual token lifetime of 10 minutes.
    private static readonly TimeSpan TokenCacheDuration = new TimeSpan(0, 5, 0);