PerlMonger79 has asked for the wisdom of the Perl Monks concerning the following question:

Hi guys, I am currently using Postman to manually generate an access token for my perl script to get data from an API, but it expires every hour. However, I would like to create a perl script to make the access token request and pass that token to my other script. With the sample code I'm using I get a 400 Bad Request message. Can you please help me and tell me if I'm missing a parameter? For security, I've ommited the credential values.
#!/usr/bin/perl -w use strict; use warnings; use LWP::UserAgent; my $netloc = "xxx.xx.xx"; my $realm = "realm"; my $user = "usercode"; my $pass = "passcode"; my $ua = LWP::UserAgent->new(); $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0; $ua->default_header( "Accept" => "application/json" ); $ua->default_header( "Content-Type" => "application/json"); $ua->credentials( $netloc, $realm, $user, $pass); $ua->ssl_opts( verify_hostname => 0, SSL_verify_mode => 0x00); my $query = "https://".$netloc."/api/v2/access/token"; my $req = HTTP::Request->new( GET => $query); my $resp = $ua->request($req); if ($resp->is_success) { my $output = $resp->decoded_content; print $output."\n"; } else { print STDERR $resp->status_line, "\n"; }

Replies are listed 'Best First'.
Re: Getting an Access Token
by tangent (Parson) on Mar 05, 2022 at 00:37 UTC
    In Postman you should be able to see the details of your request in the Postman console - see this page. If you can copy those details (obscuring the credential values) and post them here it should be easy enough for us to help.
      Hi. When I open the postman application and request a token manually, I get the following in the console.
      POST https://xxx.xx.xx.xx/api/v2/access/token 200 62 ms Warning: Self signed certificate POST /api/v2/access/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded Authorization: Basic bGJLN0dLaGNmVTM2MkxNbjpzOUtKRXR0UVBHeGIyTkxkcEpMM +3hHbmlLN0MwaUk= User-Agent: PostmanRuntime/7.29.0 Accept: */* Cache-Control: no-cache Postman-Token: 1979ab3e-0607-4544-a239-05d37cb2dd87 Host: 172.20.19.21 Accept-Encoding: gzip, deflate, br Connection: keep-alive Content-Length: 29 grant_type=client_credentials HTTP/1.1 200 OK Server: nginx Date: Sat, 05 Mar 2022 07:31:30 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive ETag: W/"63-lVO9g4PVOvVMxmtOQ57cFQLhFck" Strict-Transport-Security: max-age=31536000; includeSubDomains Content-Encoding: gzip {"access_token":"16f7a07cc25b2cf3618b8286180eb264744e145f","expires_in +":3600,"token_type":"bearer"}
      I'm trying to use the following perl script to request the token. But I get a Bad Request error.
      #!/usr/bin/perl -w use strict; use warnings; use LWP::UserAgent; my $netloc = "xxx.xx.xx.xx"; my $realm = "Realm"; my $user = "usercode"; my $pass = "passcode"; my $ua = LWP::UserAgent->new(); $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0; $ua->default_header( "Authorization" => "Basic bGJLN0dLaGNmVTM2MkxNbjp +zOUtKRXR0UVBHeGIyTkxkcEpMM3hHbmlLN0MwaUk="); $ua->default_header( "Accept" => "*/*" ); $ua->default_header( "Content-Type" => "application/x-www-form-urlenco +ded"); $ua->credentials( $netloc, $realm, $user, $pass); $ua->ssl_opts( verify_hostname => 0, SSL_verify_mode => 0x00); my $query = "https://".$netloc."/api/v2/access/token"; my $req = HTTP::Request->new( POST => $query); my $resp = $ua->request($req); if ($resp->is_success) { my $output = $resp->decoded_content; print $output."\n"; } else { print $resp->as_string(); }
      I get this reponse...
      [user@localhost wifi]$ ./wifi-api-test-token.pl HTTP/1.1 400 Bad Request Connection: close Date: Sat, 05 Mar 2022 07:34:43 GMT ETag: W/"1b-WJVp2bnCdBNm40JHvp3t41llPJs" Server: nginx Content-Length: 27 Content-Type: application/json; charset=utf-8 Client-Date: Sat, 05 Mar 2022 07:35:10 GMT Client-Peer: 172.20.19.21:443 Client-Response-Num: 1 Client-SSL-Cert-Issuer: /O=Cambium Networks Ltd. Client-SSL-Cert-Subject: /O=Cambium Networks Ltd. Client-SSL-Cipher: ECDHE-RSA-AES128-GCM-SHA256 Client-SSL-Socket-Class: IO::Socket::SSL Client-SSL-Version: TLSv1_2 Client-SSL-Warning: Peer certificate not verified Strict-Transport-Security: max-age=31536000; includeSubDomains {"error":"invalid_request"}
        OK guys, it's ok I figured it out through viewing several other script examples. So this is my final script.
        #!/usr/bin/perl -w use strict; use warnings; use LWP::UserAgent; my $netloc = "xxx.xx.xx.xx"; my $realm = "Realm"; my $user = "usercode"; my $pass = "passcode"; my $ua = LWP::UserAgent->new(); $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0; $ua->default_header( "Authorization" => "Basic bGJLN0dLaGNmVTM2MkxNbjp +zOUtKRXR0UVBHeGIyTkxkcEpMM3hHbmlLN0MwaUk="); $ua->default_header( "Accept" => "*/*" ); $ua->default_header( "Content-Type" => "application/x-www-form-urlenco +ded"); $ua->credentials( $netloc, $realm, $user, $pass); $ua->ssl_opts( verify_hostname => 0, SSL_verify_mode => 0x00); my $url = "https://".$netloc."/api/v2/access/token"; my $resp = $ua->post($url, Content => ['grant_type' => "client_creden +tials"]); if ($resp->is_success) { my $output = $resp->decoded_content; print $output."\n"; } else { print $resp->as_string(); }
        And I now get the following output.
        {"access_token":"ea1dda77710f64b0db328415427a1463e74ea204","expires_in +":3600,"token_type":"bearer"}
        Thank you for taking time and steering me in the right direction. That postman console really helped me a lot. Thank you very much.
Re: Getting an Access Token
by NetWallah (Canon) on Mar 04, 2022 at 23:31 UTC
    I believe your request payload needs to include json encoded user and password info (I have not tried $ua->credentials).

    Your $resp object content should show more details of what the server is expecting.
    Try dumping it with Data::Dumper or equivalent.

                    "These opinions are my own, though for a small fee they be yours too."

Re: Getting an Access Token
by Marshall (Canon) on Mar 04, 2022 at 22:15 UTC
    I don't understand your exact question. Does the code you show above fail?
    If so, what does that have to do with credentials needing to be renewed every hour?

    Get your code working without consideration of expired credentials. Then add that consideration later.

    Perl redo could be and probably is appropriate, but I am not able to judge here.