How to use URLFetch for a https secure automated login?

This api isn't accessible in the US, which makes it difficult to post a working code.

Try:

myCert = Import["path/to/my.crt"];

file = FileNameJoin[{
                     Replace["Location",PacletInformation["HTTPClient"]],
                     "SSL",
                     "cacert.pem"
                     }];

(*Append your certificate to the existing cacert.pem file*)
o = OpenAppend[file];
WriteString[o, "\n" <> myCert];
Close[o];

URLFetch[ "https://identitysso.betfair.com/api/certlogin",
    { "StatusCode", "Headers", "Content" },
    Method->"POST",
    "Headers" -> {
        "X-Application" -> "nilostep",
        "Content-Type" -> "application/x-www-form-urlencoded",
        "Accept" -> "application/json", 
        "Username" -> "myusername",
        "Password" -> "mypassword"
    }
]

On SSL and cert files

So this seems to fundamentally be a question of doing SSL certification. Going from here there's some discussion of adding SSL certificates in a standard location. Here's a way to find your equivalent of that file:

$CAFile =
  First@FileNames["*.pem", $InstallationDirectory, \[Infinity]];

Mine lives here:

FileNameJoin@{$InstallationDirectory, "SystemFiles", "Links", 
  "CURLLink", "SSL", "cacert.pem"}

And as URLRead calls URLFetch, which in turn calls the CURLLink system I think this is the right place to append my credentials.

Here's a wholly untested way to do this (as I have no .pem files to test it with) without copying it in by hand:

CAAppend[cert_String?(Not@*FileExistsQ)] :=

  If[Not@StringContainsQ[Import[$CAFile, "Text"], cert],
   CopyFile[$CAFile,
    FileNameJoin@{DirectoryName@$CAFile,
      FileBaseName@$CAFile <> "_backup." <> FileExtension@$CAFile
      }];
   With[{append = OpenAppend[$CAFile]},
    WriteString[append, cert];
    Close@append;
    ]
   ];
CAAppend[cert_String?FileExistsQ] :=
  CAAppend@Import[cert, "Text"];

Obviously the best way would be to find some way to pass the necessary SSL cert data in the headers of an http request, but that'll take more research.

Original posting

Since you mention you're on 11. have you tried formatting an HTTPRequest instead? I've had success using it to get an application-only access token off of Twitter. Basically I followed their guide and ended up with this:

HTTPRequest[
  <|
   "Scheme" -> "https",
   "Domain" -> "api.twitter.com",
   "Path" -> {"oauth2", "token"}
   |>,
  <|
   "Host" -> "api.twitter.com",
   "Body" ->
    {"grant_type" -> "client_credentials"},
   "UserAgent" ->
    $consumerName,
   "Headers" -> {
     "Authorization" ->
      "Basic " <> $bearerToken
     }
   |>
  ] // Import

then translating that over to the template you had I ran this (note that when you have your real $cert files you should uncomment File/@ in $cert.

$cert =
  (*File/@*){"client-2048.crt", "client-2048.key"};
$username =
  "myusername";
$password =
  "mypassword";
$application =
  "SomeKey";
HTTPRequest[
  <|
   "Scheme" -> "https",
   "Domain" -> "identitysso.w-con.betfair.com",
   "Path" -> {"api", "certlogin"}
   |>,
  <|
   "Headers" -> {
     "X-Application" ->
      $application
     },
   "Body" -> {
     "username" ->
      $username,
     "password" ->
      $password,
     "cert" ->
      $cert
     }
   |>
  ] // Import[#, "JSON"] &

Executing that returns:

{"loginStatus" -> "ACCOUNT_ALREADY_LOCKED"}

Which tells me that something is happening. Try dropping in your credentials and see what happens.


The following solution is a working workaround.

Needs["JLink`"]
BOTA = "D:\\Dropbox\\DATA\\MyJavaProjects\\bota\\out\\artifacts\\bota_jar\\bota.jar";
ReinstallJava[CommandLine -> "C:\\Progra~1\\Java\\jdk1.8.0_45\\jre\\bin\\java", ClassPath -> BOTA];
conn = JavaNew["org.nilostep.bota.HttpClientSSO"]
conn@getSessionKey[]

bota.jar contains the class HttpClientSSO as described in the API manual ( see question ) with an additional method that returns the sessionkey as a string.

Classpath is the path to bota.jar

getSessionKey() returns a String and is a new method in HttpClientSSO

The above should be possible with just URLFetch though.

Tags:

Web Access