Hallo,
ich habe endlich erste Erfolge in der Portierung, ich konnte ein Token holen und refreshen.
Ich bitte darum, das jeder, der mag, dieses Script mal ablaufen lässt, natürlich mit eigenem user und password
<?php
declare(strict_types=1);
$user = 'xxx@tdl';
$password = 'zzzz';
$with_debug = false;
function urlsafe_b64encode($string)
{
$data = base64_encode($string);
$data = str_replace(['+', '/'], ['-', '_'], $data);
$data = rtrim($data, '=');
return $data;
}
$region = 'RestOfWorld';
$oauth_config_url = '/eadrax-ucs/v1/presentation/oauth/config';
$server_urls_eadrax = [
'NorthAmerica' => 'cocoapi.bmwgroup.us',
'RestOfWorld' => 'cocoapi.bmwgroup.com',
];
$ocp_apim_key = [
'NorthAmerica' => '31e102f5-6f7e-7ef3-9044-ddce63891362',
'RestOfWorld' => '4f1c85a3-758f-a37d-bbb6-f8704494acfa',
];
$baseurl = 'https://' . $server_urls_eadrax[$region];
$x_user_agent_pre = 'android(v1.07_20200330);';
$x_user_agent_post = ';1.7.0(11152)';
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
curl_setopt($ch, CURLOPT_MAXREDIRS, 50);
curl_setopt($ch, CURLOPT_HTTP09_ALLOWED, true);
curl_setopt($ch, CURLOPT_TCP_KEEPALIVE, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, '');
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
echo '*** get config' . PHP_EOL;
$config_url = $baseurl . '/' . $oauth_config_url;
$header = [
'ocp-apim-subscription-key: ' . $ocp_apim_key[$region],
'x-user-agent: ' . $x_user_agent_pre . 'bmw' . $x_user_agent_post,
];
echo 'config_url=' . $config_url . PHP_EOL;
if ($with_debug) {
echo 'header=' . print_r($header, true) . PHP_EOL;
}
curl_setopt($ch, CURLOPT_URL, $config_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$response = curl_exec($ch);
$cerrno = curl_errno($ch);
$cerror = $cerrno ? curl_error($ch) : '';
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_info = curl_getinfo($ch);
$header_size = $curl_info['header_size'];
$head = substr($response, 0, $header_size);
$body = substr($response, $header_size);
echo 'errno=' . $cerrno . '(' . $cerror . '), httpcode=' . $httpcode . PHP_EOL;
echo 'body=' . $body . PHP_EOL;
$oauth_settings = json_decode($body, true);
if ($with_debug) {
echo 'oauth_settings=' . print_r($oauth_settings, true) . PHP_EOL;
}
echo PHP_EOL;
echo '*** authenticate, step 1' . PHP_EOL;
# Setting up PKCS data
$verifier_bytes = random_bytes(64);
$code_verifier = urlsafe_b64encode($verifier_bytes);
//echo 'code_verifier='.$code_verifier.PHP_EOL;
$challenge_bytes = hash('sha256', $code_verifier, true);
$code_challenge = urlsafe_b64encode($challenge_bytes);
//echo 'code_challenge='.$code_challenge.PHP_EOL;
$state_bytes = random_bytes(16);
$state = urlsafe_b64encode($state_bytes);
//echo 'state='.$state.PHP_EOL;
$oauth_authenticate_url = '/gcdm/oauth/authenticate';
$gcdm_base_url = $oauth_settings['gcdmBaseUrl'];
$auth_url = $gcdm_base_url . $oauth_authenticate_url;
$header = [
'Content-Type: application/x-www-form-urlencoded',
];
$oauth_base_values = [
'client_id' => $oauth_settings['clientId'],
'response_type' => 'code',
'redirect_uri' => $oauth_settings['returnUrl'],
'state' => $state,
'nonce' => 'login_nonce',
'scope' => implode(' ', $oauth_settings['scopes']),
'code_challenge' => $code_challenge,
'code_challenge_method' => 'S256',
];
if ($with_debug) {
echo 'oauth_base_values=' . print_r($oauth_base_values, true) . PHP_EOL;
}
$postfields = $oauth_base_values;
$postfields['grant_type'] = 'authorization_code';
$postfields['username'] = $user;
$postfields['password'] = $password;
echo 'auth_url=' . $auth_url . PHP_EOL;
if ($with_debug) {
echo 'header=' . print_r($header, true) . PHP_EOL;
echo 'postfields=' . print_r($postfields, true) . PHP_EOL;
}
curl_setopt($ch, CURLOPT_URL, $auth_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postfields));
$response = curl_exec($ch);
$cerrno = curl_errno($ch);
$cerror = $cerrno ? curl_error($ch) : '';
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_info = curl_getinfo($ch);
$header_size = $curl_info['header_size'];
$head = substr($response, 0, $header_size);
$body = substr($response, $header_size);
preg_match_all('|Set-Cookie: (.*);|U', $head, $results);
$cookies = explode(';', implode(';', $results[1]));
echo 'errno=' . $cerrno . '(' . $cerror . '), httpcode=' . $httpcode . PHP_EOL;
if ($with_debug) {
echo 'body=' . $body . PHP_EOL;
echo 'cookies=' . print_r($cookies, true) . PHP_EOL;
}
$jbody = json_decode($body, true);
if ($with_debug) {
echo 'jbody=' . print_r($jbody, true) . PHP_EOL;
}
$redirect_uri = substr($jbody['redirect_to'], strlen('redirect_uri='));
$redirect_parts = parse_url($redirect_uri);
if ($with_debug) {
echo 'redirect_parts=' . print_r($redirect_parts, true) . PHP_EOL;
}
if ($redirect_parts == false || isset($redirect_parts['query']) == false) {
echo 'missing element "query" in "' . $redirect_uri . '"' . PHP_EOL;
return false;
}
parse_str($redirect_parts['query'], $redirect_opts);
if ($with_debug) {
echo 'redirect_opts=' . print_r($redirect_opts, true) . PHP_EOL;
}
foreach (['authorization'] as $key) {
if (isset($redirect_opts[$key]) == false) {
echo 'missing element "' . $key . '" in "' . $redirect_parts['query'] . '"' . PHP_EOL;
return false;
}
}
echo 'authorization="' . $redirect_opts['authorization'] . '"' . PHP_EOL;
echo PHP_EOL;
echo '*** authenticate, step 2' . PHP_EOL;
$postfields = $oauth_base_values;
$postfields['authorization'] = $redirect_opts['authorization'];
$header = [
'Content-Type: application/x-www-form-urlencoded',
];
foreach ($cookies as $cookie) {
$header[] = 'Cookie: ' . $cookie;
}
echo 'auth_url=' . $auth_url . PHP_EOL;
if ($with_debug) {
echo 'header=' . print_r($header, true) . PHP_EOL;
echo 'postfields=' . print_r($postfields, true) . PHP_EOL;
}
curl_setopt($ch, CURLOPT_URL, $auth_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postfields));
$response = curl_exec($ch);
$cerrno = curl_errno($ch);
$cerror = $cerrno ? curl_error($ch) : '';
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_info = curl_getinfo($ch);
$header_size = $curl_info['header_size'];
$head = substr($response, 0, $header_size);
$body = substr($response, $header_size);
echo 'errno=' . $cerrno . '(' . $cerror . '), httpcode=' . $httpcode . PHP_EOL;
if ($with_debug) {
echo 'head=' . $head . PHP_EOL;
echo 'body=' . $body . PHP_EOL;
}
preg_match_all('|location: (.*)|', $head, $results);
if ($with_debug) {
echo 'results=' . print_r($results, true) . PHP_EOL;
}
$location = $results[1][0];
$location_parts = parse_url($location);
if ($with_debug) {
echo 'location_parts=' . print_r($location_parts, true) . PHP_EOL;
}
if ($location_parts == false || isset($location_parts['query']) == false) {
echo 'missing element "query" in "' . $location . '"' . PHP_EOL;
return false;
}
parse_str($location_parts['query'], $location_opts);
if ($with_debug) {
echo 'location_opts=' . print_r($location_opts, true) . PHP_EOL;
}
foreach (['code'] as $key) {
if (isset($location_opts[$key]) == false) {
echo 'missing element "' . $key . '" in "' . $location_opts['query'] . '"' . PHP_EOL;
return false;
}
}
echo PHP_EOL;
echo '*** get token' . PHP_EOL;
$oauth_authorization = base64_encode($oauth_settings['clientId'] . ':' . $oauth_settings['clientSecret']);
$token_url = $oauth_settings['tokenEndpoint'];
$header[] = 'Authorization: Basic ' . $oauth_authorization;
$postfields = [
'code' => $location_opts['code'],
'code_verifier' => $code_verifier,
'redirect_uri' => $oauth_settings['returnUrl'],
'grant_type' => 'authorization_code',
];
echo 'token_url=' . $token_url . PHP_EOL;
if ($with_debug) {
echo 'header=' . print_r($header, true) . PHP_EOL;
echo 'postfields=' . print_r($postfields, true) . PHP_EOL;
}
curl_setopt($ch, CURLOPT_URL, $token_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postfields));
$response = curl_exec($ch);
$cerrno = curl_errno($ch);
$cerror = $cerrno ? curl_error($ch) : '';
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_info = curl_getinfo($ch);
$header_size = $curl_info['header_size'];
$head = substr($response, 0, $header_size);
$body = substr($response, $header_size);
echo 'errno=' . $cerrno . '(' . $cerror . '), httpcode=' . $httpcode . PHP_EOL;
if ($with_debug) {
echo 'body=' . $body . PHP_EOL;
}
$jbody = json_decode($body, true);
if ($with_debug) {
echo 'jbody=' . print_r($jbody, true) . PHP_EOL;
}
foreach (['access_token', 'refresh_token', 'expires_in'] as $key) {
if (isset($jbody[$key]) == false) {
echo 'missing element "query" in "' . $body . '"' . PHP_EOL;
return false;
}
}
$access_token = $jbody['access_token'];
$refresh_token = $jbody['refresh_token'];
$expires_in = $jbody['expires_in'];
echo 'access_token=' . $access_token . ', refresh_token=' . $refresh_token . ', expires_in=' . $expires_in . PHP_EOL;
echo PHP_EOL;
$header = [
'Content-Type: application/x-www-form-urlencoded',
'Authorization: Basic ' . $oauth_authorization,
];
$postfields = [
'grant_type' => 'refresh_token',
'refresh_token' => $refresh_token,
];
$token_url = $oauth_settings['tokenEndpoint'];
echo '*** refresh token' . PHP_EOL;
echo 'token_url=' . $token_url . PHP_EOL;
if ($with_debug) {
echo 'header=' . print_r($header, true) . PHP_EOL;
echo 'postfields=' . print_r($postfields, true) . PHP_EOL;
}
curl_setopt($ch, CURLOPT_URL, $token_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postfields));
curl_setopt($ch, CURLOPT_HEADER, true);
$response = curl_exec($ch);
$cerrno = curl_errno($ch);
$cerror = $cerrno ? curl_error($ch) : '';
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_info = curl_getinfo($ch);
$header_size = $curl_info['header_size'];
$head = substr($response, 0, $header_size);
$body = substr($response, $header_size);
echo 'errno=' . $cerrno . '(' . $cerror . '), httpcode=' . $httpcode . PHP_EOL;
if ($with_debug) {
echo 'body=' . $body . PHP_EOL;
}
$jbody = json_decode($body, true);
if ($with_debug) {
echo 'jbody=' . print_r($jbody, true) . PHP_EOL;
}
$access_token = $jbody['access_token'];
$refresh_token = $jbody['refresh_token'];
$expires_in = $jbody['expires_in'];
foreach (['access_token', 'refresh_token', 'expires_in'] as $key) {
if (isset($jbody[$key]) == false) {
echo 'missing element "query" in "' . $body . '"' . PHP_EOL;
return false;
}
}
echo 'access_token=' . $access_token . ', refresh_token=' . $refresh_token . ', expires_in=' . $expires_in . PHP_EOL;
Die Antwort sollte etwa wie folgt sein
*** get config
config_url=https://cocoapi.bmwgroup.com//eadrax-ucs/v1/presentation/oauth/config
errno=0(), httpcode=200
body={"clientName":"mybmwapp","clientSecret":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","clientId":"yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy","gcdmBaseUrl":"https://customer.bmwgroup.com","returnUrl":"com.bmw.connected://oauth","brand":"bmw","language":"en","country":"US","authorizationEndpoint":"https://customer.bmwgroup.com/oneid/login","tokenEndpoint":"https://customer.bmwgroup.com/gcdm/oauth/token","scopes":["openid","profile","email","offline_access","smacc","vehicle_data","perseus","dlm","svds","cesim","vsapi","remote_services","fupo","authenticate_user"],"promptValues":["login"]}
*** authenticate, step 1
auth_url=https://customer.bmwgroup.com/gcdm/oauth/authenticate
errno=0(), httpcode=200
authorization="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
*** authenticate, step 2
auth_url=https://customer.bmwgroup.com/gcdm/oauth/authenticate
errno=0(), httpcode=302
*** get token
token_url=https://customer.bmwgroup.com/gcdm/oauth/token
errno=0(), httpcode=200
access_token=aaaaaaaaaaaaaaaaaaaaaaaaaaa, refresh_token=rrrrrrrrrrrrrrrrrrrrrrrrrrr, expires_in=3599
*** refresh token
token_url=https://customer.bmwgroup.com/gcdm/oauth/token
errno=0(), httpcode=200
access_token=aaaaaaaaaaaaaaaaaaaaaaaaaaa, refresh_token=rrrrrrrrrrrrrrrrrrrrrrrrrrr, expires_in=3599
würde mich über Antworten freuen
demel