我创建了一个安全配置文件并从中获取了CODE_CHALLENGE。我引用了How to Authenticate with Alexa Voice Service from Android?。
private static final String PRODUCT_ID = "my_device";
private static final String PRODUCT_DSN = "123";
private static final String CODE_CHALLENGE = "ca9416f4aaafc68f0722e38410f9acd18094a9b9f59e0c10a1cf8930b3d8600f";
private static final String CODE_CHALLENGE_METHOD = "S256";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_amazon_login);
requestContext = RequestContext.create(this);
requestContext.registerListener(new AuthorizeListenerImpl());
buttonAmazon = (Button)findViewById(R.id.button_amazon);
buttonAmazon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final JSONObject scopeData = new JSONObject();
final JSONObject productInstanceAttributes = new JSONObject();
try {
productInstanceAttributes.put("deviceSerialNumber", PRODUCT_DSN);
scopeData.put("productInstanceAttributes", productInstanceAttributes);
scopeData.put("productID", PRODUCT_ID);
AuthorizationManager.authorize(new AuthorizeRequest.Builder(requestContext)
.addScope(ScopeFactory.scopeNamed("alexa:all", scopeData))
.forGrantType(AuthorizeRequest.GrantType.AUTHORIZATION_CODE)
.withProofKeyParameters(CODE_CHALLENGE, CODE_CHALLENGE_METHOD)
.build());
} catch (JSONException e) {
// handle exception here
}
}
});
}
private class AuthorizeListenerImpl extends AuthorizeListener {
/* Authorization was completed successfully. */
@Override
public void onSuccess(final AuthorizeResult authorizeResult) {
final String authorizationCode = authorizeResult.getAuthorizationCode();
final String redirectUri = authorizeResult.getRedirectURI();
final String clientId = authorizeResult.getClientId();
Log.d("AmazonLoginActivity","success"+" "+authorizationCode+" "+redirectUri+" "+clientId);
postData(authorizationCode,redirectUri,clientId);
}
/* There was an error during the attempt to authorize the application. */
@Override
public void onError(final AuthError authError) {
}
/* Authorization was cancelled before it could be completed. */
@Override
public void onCancel(final AuthCancellation authCancellation) {
}
}
public void postData(String s1, String s2, String s3) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://api.amazon.com/auth/O2/token");
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("grant_type", "authorization_code"));
nameValuePairs.add(new BasicNameValuePair("code", s1));
nameValuePairs.add(new BasicNameValuePair("redirect_uri", s2));
nameValuePairs.add(new BasicNameValuePair("client_id", s3));
nameValuePairs.add(new BasicNameValuePair("code_verifier","1234"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
String responseStr = EntityUtils.toString(response.getEntity());
Header[] headers = response.getAllHeaders();
for (Header header : headers) {
System.out.println("Key : " + header.getName()
+ " ,Value : " + header.getValue());
}
Log.d("Response",responseStr);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
} catch (IOException e) {
// TODO Auto-generated catch block
}
}
我正在收到unauthorized_client异常。这是我的安卓日志。
06-23 18:31:02.496 29161-29523/gct.venkatesh.com.alexabot I/com.amazon.identity.auth.device.authorization.AuthorizationHelper: Return auth code success
06-23 18:31:02.500 29161-29523/gct.venkatesh.com.alexabot D/AmazonLoginActivity: success ANkBjQgTSnsVwfcQCqrU amzn://gct.venkatesh.com.alexabot amzn1.application-oa2-client.bd04c0584c0c4a1296bf3c1f14f9a831
06-23 18:31:02.611 29161-29161/gct.venkatesh.com.alexabot I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@1496318b time:21809219
06-23 18:31:04.543 29161-29523/gct.venkatesh.com.alexabot I/System.out: Key : Server ,Value : Server
06-23 18:31:04.544 29161-29523/gct.venkatesh.com.alexabot I/System.out: Key : Date ,Value : Fri, 23 Jun 2017 13:00:42 GMT
06-23 18:31:04.544 29161-29523/gct.venkatesh.com.alexabot I/System.out: Key : Content-Type ,Value : application/json
06-23 18:31:04.544 29161-29523/gct.venkatesh.com.alexabot I/System.out: Key : Content-Length ,Value : 92
06-23 18:31:04.544 29161-29523/gct.venkatesh.com.alexabot I/System.out: Key : Connection ,Value : keep-alive
06-23 18:31:04.544 29161-29523/gct.venkatesh.com.alexabot I/System.out: Key : x-amzn-RequestId ,Value : f6f231ed-5813-11e7-88b7-1d51a9cde1df
06-23 18:31:04.544 29161-29523/gct.venkatesh.com.alexabot I/System.out: Key : X-Amz-Date ,Value : Fri, 23 Jun 2017 13:00:42 GMT
06-23 18:31:04.544 29161-29523/gct.venkatesh.com.alexabot I/System.out: Key : x-amzn-ErrorType ,Value : OA2UnauthorizedClientException:http://internal.amazon.com/coral/com.amazon.panda/
06-23 18:31:04.544 29161-29523/gct.venkatesh.com.alexabot I/System.out: Key : Cache-Control ,Value : no-cache, no-store, must-revalidate
06-23 18:31:04.544 29161-29523/gct.venkatesh.com.alexabot I/System.out: Key : Pragma ,Value : no-cache
06-23 18:31:04.544 29161-29523/gct.venkatesh.com.alexabot I/System.out: Key : Vary ,Value : Accept-Encoding,User-Agent
06-23 18:31:04.544 29161-29523/gct.venkatesh.com.alexabot D/Response: {"error_description":"Not authorized for requested operation","error":"unauthorized_client"
答案 0 :(得分:-2)
@Venkatesh:
生成codeVerifier和codeChallenge:
String codeVerifier = generateCodeVerifier();
String codeChallenge = generateCodeChallenge(codeVerifier, "S256");
private String generateCodeVerifier() {
String randomOctetSequence = generateRandomOctetSequence(100);
String codeVerifier = base64UrlEncode(randomOctetSequence.getBytes());
return codeVerifier;
}
private String generateRandomOctetSequence(int count) {
char[] chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_.~".toCharArray();
StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i = 0; i < count; i++) {
char c = chars[random.nextInt(chars.length)];
sb.append(c);
}
return sb.toString();
}
private String generateCodeChallenge(String codeVerifier, String codeChallengeMethod) {
String codeChallenge = "";
if ("S256".equalsIgnoreCase(codeChallengeMethod)) {
try {
byte[] digest = MessageDigest.getInstance("SHA-256").digest(
codeVerifier.getBytes());
codeChallenge = base64UrlEncode(
digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
} else {
// Fall back to code_challenge_method = "plain" codeChallenge = codeVerifier;
}
return codeChallenge;
}
private String base64UrlEncode(byte[] arg) {
String s = new String(Base64.encode(arg, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP));
s = s.split("=")[0]; // Remove any trailing '='s
s = s.replace('+', '-'); // 62nd char of encoding
s = s.replace('/', '_'); // 63rd char of encoding
return s;
}
Plz在这里看到我的评论(来源):https://github.com/alexa/alexa-avs-sample-app/issues/987