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: “
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.
encrypter
When the state value is stored locally, it is encrypted. This
parameter allows you to provide your own encryption method. This will be
used in addition to the default encryption method. This will be performed
before the default encryption method.
Returns the state
value that 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<String> remoteAuthRequest({
required String clientId,
required String redirectUri,
String? deviceName,
String? state,
String Function(String plaintext)? encrypter,
}) 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");
}
// Write the state secret to local storage.
await LocalStorageRepo.write(
content: stateBuffer.toString(),
folder: Folder.tmp,
fileName: stateSecretFile,
encrypter: encrypter,
);
// Call the service.
await BridgeDiscoveryService.remoteAuthRequest(url: urlBuffer.toString());
return stateBuffer.toString();
}