remoteAuthRequest static method
This method allows the user to grant access to the app to allow it to connect to their bridge.
This is step 1. Step 2 is TokenRepo.fetchRemoteToken.
clientId
Identifies the client that is making the request. The value
passed in this parameter must exactly match the value you receive from
hue.
redirectUri
This parameter must exactly match the one configured in your
hue developer account.
deviceName
The device name should be the name of the app or device
accessing the remote API. The deviceName
is used in the user’s “My Apps”
overview in the Hue Account (visualized as: “appName
on deviceName
”).
state
Provides any state that might be useful to your application upon
receipt of the response. The Hue Authorization Server round-trips this
parameter, so your application receives the same value it sent. To
mitigate against cross-site request forgery (CSRF), a long (30+ digit),
random number is prepended to state
. When the response is received from
Hue, it is recommended that you compare the string returned from this
method, to the one that is returned from Hue.
Returns a map with the key url
and state
. The url
is the URL that
the user needs to visit to grant access to the app. The state
value is
what is sent with the GET request. This is prepended with the long, random
number. Between the random number and the provided state
will be a -
(dash).
Implementation
static Future<Map<String, String>> remoteAuthRequest({
required String clientId,
required String redirectUri,
String? deviceName,
String? state,
}) async {
final StringBuffer urlBuffer =
StringBuffer('https://api.meethue.com/v2/oauth2/authorize?');
final StringBuffer stateBuffer = StringBuffer();
// Generate a random code verifier.
final String codeVerifier = base64Url
.encode(List.generate(32, (index) => MiscTools.randInt(0, 255)));
// Calculate the code challenge using SHA-256.
final String codeChallenge =
base64Url.encode(sha256.convert(utf8.encode(codeVerifier)).bytes);
// Write the URI.
urlBuffer.write('${ApiFields.clientId}=$clientId');
urlBuffer.write('&${ApiFields.responseType}=code');
urlBuffer.write('&${ApiFields.codeChallengeMethod}=S256');
urlBuffer.write('&${ApiFields.codeChallenge}=$codeChallenge');
urlBuffer.write('&${ApiFields.state}=');
stateBuffer.write(MiscTools.randInt(1, 123).toString());
for (int i = 0; i < MiscTools.randInt(30, 44); i++) {
stateBuffer.write(MiscTools.randInt(0, 123).toString());
}
urlBuffer.write(stateBuffer.toString());
if (state != null && state.isNotEmpty) {
urlBuffer.write('-$state');
}
urlBuffer.write('&${ApiFields.redirectUri}=$redirectUri');
if (deviceName != null && deviceName.isNotEmpty) {
urlBuffer.write('&${ApiFields.deviceName}=$deviceName');
}
return {'url': urlBuffer.toString(), 'state': stateBuffer.toString()};
}