Response code 400 is returned when specifying a specific scope on GoogleTV - google-fit

Question
When I specify a specific scope, a response code of 400 is returned and I am unable to go to the authentication screen.
【400 error scope】
https://www.googleapis.com/auth/fitness.heart_rate.read
https://www.googleapis.com/auth/fitness.blood_pressure.read
https://www.googleapis.com/auth/fitness.body_temperature.read
【200 OK scope】
https://www.googleapis.com/auth/fitness.body.read
https://www.googleapis.com/auth/fitness.activity.read
If you know why the response code is different between 200 and 400 even though it is the same FitnessApi, please let me know.
Also, the scope for profile and email is returned at 200 normally.
Notes
Google Cloud Platform Settings
We have enabled the FitnessAPI.
For authentication information, client ID and client secret are generated using "Client ID for TVs and devices with limited input functions".
The Fitness scope described above is set in the OAuth consent screen settings of the Google Cloud Platform.
Relevant source
private static final String OAUTH_CODE_URL = "https://oauth2.googleapis.com/device/code";
private static final String OAUTH_TOKEN_URL = "https://oauth2.googleapis.com/token";
private static final String SCOPE_FITNESS_BODY = "https://www.googleapis.com/auth/fitness.body.read";
private static final String SCOPE_FITNESS_ACTIVITY = "https://www.googleapis.com/auth/fitness.activity.read";
private static final String SCOPE_FITNESS_HEART_RATE = "https://www.googleapis.com/auth/fitness.heart_rate.read";
private static final String SCOPE_FITNESS_BLOOD_PRESSURE = "https://www.googleapis.com/auth/fitness.blood_pressure.read";
private static final String SCOPE_FITNESS_BODY_TEMPERATURE = "https://www.googleapis.com/auth/fitness.body_temperature.read";
private static final String SCOPE_EMAIL = "email";
private static final String SCOPE_PROFILE = "profile";
:
public Object[] postAccessToken() {
String postBody = "client_id=" + OAUTH_CLIENT_ID +
"&scope=" + SCOPE_EMAIL +
"%20" + SCOPE_FITNESS_BODY_TEMPERATURE +
"%20" + SCOPE_FITNESS_ACTIVITY +
"%20" + SCOPE_FITNESS_BODY +
"%20" + SCOPE_FITNESS_HEART_RATE +
"%20" + SCOPE_FITNESS_BLOOD_PRESSURE +
"%20" + SCOPE_PROFILE;
return postAPI(OAUTH_CODE_URL, postBody);
}
:
public Object[] postAPI(String sendUrl, String sendPostData) {
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
OutputStream outputStream = null;
String result = "";
String str = "";
int statusCode = 0;
try {
URL url = new URL(sendUrl);
urlConnection = (HttpURLConnection) url.openConnection();
String postData = sendPostData;
urlConnection.setConnectTimeout(5000);
urlConnection.setReadTimeout(5000);
urlConnection.addRequestProperty("User-Agent", "Android");
urlConnection.addRequestProperty("Accept-Language", Locale.getDefault().toString());
urlConnection.setRequestMethod("POST");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.connect();
outputStream = urlConnection.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, "utf-8"));
bufferedWriter.write(postData);
bufferedWriter.flush();
bufferedWriter.close();
// Get the response code
statusCode = urlConnection.getResponseCode();

OAuth 2.0 flow for TV and limited-input device applications have limited access scopes. However, these scopes are supported for other authentication flows, such as for mobile/desktop apps, and web apps.
The OAuth 2.0 flow for TV is supported only for the following scopes:
email
openid
profile

Related

How to get gmail thread id using JavaMail API in android?

As per gimap documentation javamail new gimap doc, ImapMessage not casting to GmailMessage.
Doc code is:
GmailMessage gmsg = (GmailMessage)msg; System.out.println("Gmail message ID is " + gmsg.getMsgId()); String[] labels = gmsg.getLabels(); for (String s : labels) System.out.println("Gmail message label: " + s);
here msg is a object of ImapMessage.
Error is: java.lang.ClassCastException: com.sun.mail.imap.IMAPMessage cannot be cast to com.sun.mail.gimap.mailMessage
How to solve it?
My Imap connection code is:
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Folder;
String IMAP_PROTOCOL = "imap";
String IMAP_HOST = "imap.gmail.com";
String IMAP_PORT = "993";
private Store store;
private Folder folderInbox;
private Session session;
private Properties getServerProperties(String protocol, String host,
String port) {
Properties properties = new Properties();
// server setting
properties.put(String.format("mail.%s.host", protocol), host);
properties.put(String.format("mail.%s.port", protocol), port);
// SSL setting
properties.setProperty(
String.format("mail.%s.socketFactory.class", protocol),
"javax.net.ssl.SSLSocketFactory");
properties.setProperty(
String.format("mail.%s.socketFactory.fallback", protocol),
"false");
properties.setProperty(
String.format("mail.%s.socketFactory.port", protocol),
String.valueOf(port));
return properties;
}
//Now connect gmail with imap
Properties properties = getServerProperties(protocol, host, port);
session = Session.getDefaultInstance(properties);
store = session.getStore(protocol);
store.connect(userName, password);
// opens the inbox folder
folderInbox = store.getFolder(folderName);
folderInbox.open(Folder.READ_ONLY);
// fetches new messages from server
Message[] messages = folderInbox.getMessages();
for (Message msg: messages
) {
GmailMessage gmsg = (GmailMessage)msg;
System.out.println("Gmail message ID is " + gmsg.getMsgId());
String[] labels = gmsg.getLabels();
for (String s : labels)
System.out.println("Gmail message label: " + s);
}

Unit Testing of Remote API calls, How it works with JSON Objects

In my web api, I have a method that call a service that return a deserialized JSON object. I can't find a way for unit testing that is working for me.
the following is the code from the controller:
[RequireHttps]
[Route("api/GetItem/{id}")]
public class GetItemController : ControllerBase
{
private static HttpClient client = new HttpClient();
private Item item = new Item();
[RequireHttps]
[Route("api/GetItem/{id}")]
public Item GetItem(string name, string password)
{
string url = "https://localhost:5001/";
string uri = url + "api/item/" + name+ "/" + password "/" ;
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage Res = client.GetAsync(uri).Result;
if (Res.IsSuccessStatusCode)
{
var MemResponse = Res.Content.ReadAsStringAsync().Result;
member = JsonConvert.DeserializeObject<Item>
(MemResponse);
}
return Ok(item);
}
}
The unit test I wrote suppose to check the wrong user name and password, but when running the test it just gray out and never runs
[TestMethod]
public void GetItemWithWrongPassword()
{
var username = "Hellow";
var pass = "There";
var controller = new GetItemController();
var response = controller.GetItem(username, pass);
var s = response.ToString();
Assert.AreEqual(s, "System.Web.Http.Results.NotFoundResult");
}
what I'm doing wrong?
Later on I want to test if the connection to the remote API.
Creating an instance of GetItemController and calling its methods is not a good idea, because the whole message pipeline is skipped in the process.
I see two options here:
Put the code (including the HttpClient) that is contained in GetItem into another class and call the method on an instance of that class, e.g.:
public class ItemClient
{
private static HttpClient client = new HttpClient();
public Item GetItem(string name, string password)
{
Item item = null;
string url = "https://localhost:5001/";
string uri = url + "api/item/" + name + "/" + password;
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage Res = client.GetAsync(uri).Result;
if (Res.IsSuccessStatusCode)
{
var MemResponse = Res.Content.ReadAsStringAsync().Result;
item = JsonConvert.DeserializeObject<Item>(MemResponse);
}
return item;
}
}
Controller method:
[RequireHttps]
[Route("api/GetItem/{name}/{password}")]
public Item GetItem(string name, string password)
{
ItemClient client = new ItemClient();
var item = client.GetItem(name, password);
return Ok(item);
}
Test method:
[TestMethod]
public void GetItemWithWrongPassword()
{
var username = "Hellow";
var password = "There";
ItemClient client = new ItemClient();
var item = client.GetItem(username, password);
Assert.IsNull(item);
}
Call the controller method using a HttpClient in the test method:
[TestMethod]
public void GetItemWithWrongPassword()
{
var username = "Hellow";
var password = "There";
string url = "https://localhost/"; // Host of your Web API
string uri = url + "api/GetItemController/GetItem/" + username + "/" + password;
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage Res = client.GetAsync(uri).Result;
var s = Res.ToString();
Assert.AreEqual(s, "System.Web.Http.Results.NotFoundResult");
}
I personally prefer option 1 due to two benefits:
Debugging the test is easier. Debugging a call by HttpClient (option 2)
usually means that you have to start a second instance of Visual
Studio and set a breakpoint there.
The code can be used in other projects that are not Web API services. The endpoints become simple wrappers around the actual business logic.

How to run JUnit testing on Firebase Java with authentication?

I am currently using Firebase Authentication in my mobile app. The back end is a Spring boot application. The REST APIs on the back end relies on a token generated from Firebase Authentication to retrieve the Firebase UID (verifyIDToken method) of a user to perform further functions.
Currently, I notice that in Firebase Java API (server-based), there is no way of generating a token for a user, thus there is no easy way for me to do JUnit testing on the server that relies on user authentication. Anyone has clues on how to do so?
This is the sample code that does not work:
#RequestMapping(value = "/api/subscribeChannel/{channelid}", method = RequestMethod.GET, produces = "application/json")
public DeferredResult<Object> subscribeChannel(#PathVariable Long channelid,#RequestHeader(value=FIREBASETOKEN, required = true) String idToken) {
DeferredResult<Object> result = new DeferredResult<Object>(DEFERREDTIMEOUT);
// test it out with a locally generated token
idToken = FirebaseAuth.getInstance().createCustomToken("valid Uid");
Task<FirebaseToken> task = FirebaseAuth.getInstance().verifyIdToken(idToken)
.addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
String uid = decodedToken.getUid();
logger.info("Subscribe channel on success");
// do something
ret.setStatus("success");
ret.setMessage("channel id " + channelid + " subscribed");
result.setResult(ret);
} else {
result.setErrorResult(retStatus.getMessage());
}
}
}) .addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(Exception arg0) {
Exception te = new TokenNotFoundException(idToken);
logger.error("Token Not Found for " + idToken);
result.setErrorResult(te);
}
});
return result;
}
The custom token you get is different from the ID token that you use to log on. To get an id token from a custom token, do this:
private static final String ID_TOOLKIT_URL =
"https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken";
private static final JsonFactory jsonFactory = Utils.getDefaultJsonFactory();
private static final HttpTransport transport = Utils.getDefaultTransport();
private static final String FIREBASE_API_KEY = "<your api key here>";
private String signInWithCustomToken(String customToken) throws IOException {
GenericUrl url = new GenericUrl(ID_TOOLKIT_URL + "?key="
+ FIREBASE_API_KEY);
Map<String, Object> content = ImmutableMap.<String, Object>of(
"token", customToken, "returnSecureToken", true);
HttpRequest request = transport.createRequestFactory().buildPostRequest(url,
new JsonHttpContent(jsonFactory, content));
request.setParser(new JsonObjectParser(jsonFactory));
com.google.api.client.http.HttpResponse response = request.execute();
try {
GenericJson json = response.parseAs(GenericJson.class);
return json.get("idToken").toString();
} finally {
response.disconnect();
}
}
The Java API to generate custom tokens is documented under Create custom tokens using the Firebase SDK.
From there:
String uid = "some-uid";
String customToken = FirebaseAuth.getInstance().createCustomToken(uid);

How to post messages to yammer private network

I want to post messages to yammer in different network. For this I have wrote the below code ,
it's giving the server not found exception.
rawtoken = Security.GetRawToken();
//TODO
//get list of Yammer tokens for this user
WebClient wc = new System.Net.WebClient();
wc.DownloadStringCompleted += wc_DownloadStringCompleted;
wc.DownloadStringAsync(new Uri("https://www.yammer.com/api/v1/oauth/tokens.json?access_token=" + rawtoken));
void wc_DownloadStringCompleted(object sender, System.Net.DownloadStringCompletedEventArgs e)
{
string tokens = e.Result;
MessageBox.Show(tokens);
List<Response> myDeserializedObjList = (List<Response>)Newtonsoft.Json.JsonConvert.DeserializeObject(tokens,typeof(List<Response>));
List<Response> response = myDeserializedObjList.Where(item => item.network_id == "992371").ToList();
accessToken = response[0].token;
WebClient wc = new System.Net.WebClient();
Uri uri = new Uri("https://www.yammer.com/api/v1/messages.json?access_token=" + accessToken);
student ns = new student();
// wc.Headers["Authorization"] = "Bearer " + accessToken; //use discoEN token here
String data = "group-id=" + ns.group_id + "&body=" + ns.body;
wc.UploadStringCompleted += new UploadStringCompletedEventHandler(wc_UploadStringCompleted);
wc.Headers["Content-Type"] = "application/x-www-form-urlencoded";
wc.Encoding = Encoding.UTF8;
wc.UploadStringTaskAsync(uri, data);
}
private void wc_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
MessageBox.Show(e.Result);
}
You should use the SDK for Windows Mobile rather than rolling your own code. It is available from the Yammer Developer site. Your code also passes the token on a URL parameter. This is no longer supported and you need to pass it on the authentication header.
A ServerNotFoundException highlights a connectivity problem. Perhaps you are not connected to the network, cannot route connections, or cannot resolve www.yammer.com via DNS.

NullReferenceException during navigation from MainPage.xaml.cs to another xaml

My application takes username and password and on clinking the hyperlinkbutton, these values are sent to the server and hence server returns something like PASS:ClientID. I wish to navigate to SecondPage.xaml (from MainPage.xaml.cs) only if the responseString contains PASS.
Here is my code:
namespace aquila1
{
public partial class MainPage : PhoneApplicationPage
{
static string username;
static string password;
static string rs;
static NavigationService ns = new NavigationService();
// Constructor
public MainPage()
{
InitializeComponent();
}
private static ManualResetEvent allDone = new ManualResetEvent(true);
private void HyperlinkButton_Click_1(object sender, RoutedEventArgs e)
{
username = textbox1.Text;
password = textbox2.Text;
System.Diagnostics.Debug.WriteLine(username);
System.Diagnostics.Debug.WriteLine(password);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://60.243.245.181/fms_tracking/php/mobile_login.php?username=" + username + "&password=" + password);
request.ContentType = "application/x-www-form-urlencoded";
// Set the Method property to 'POST' to post data to the URI.
request.Method = "POST";
// start the asynchronous operation
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
// Keep the main thread from continuing while the asynchronous
// operation completes. A real world application
// could do something useful such as updating its user interface.
allDone.WaitOne();
}
private static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
Stream postStream = request.EndGetRequestStream(asynchronousResult);
// Console.WriteLine("Please enter the input data to be posted:");
string postData = username + "+" + password;
System.Diagnostics.Debug.WriteLine(postData);
// Convert the string into a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Write to the request stream.
postStream.Write(byteArray, 0, postData.Length);
postStream.Close();
// Start the asynchronous operation to get the response
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private static void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
rs = responseString;
System.Diagnostics.Debug.WriteLine(responseString);
System.Diagnostics.Debug.WriteLine("#####");
System.Diagnostics.Debug.WriteLine(rs);
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
move2();
allDone.Set();
}
private static void move2()
{
string[] rs1 = rs.Split(':');
if ((rs1[0].Trim()).Equals("PASS"))
{
ns.Navigate(new Uri("/SecondPage.xaml", UriKind.Relative));
}
else
{
MessageBox.Show(rs);
}
}
}
}
On running the code, i always get NullReferenceException .
Plz help me find the error and suggest corrections.
Thanks in advance
You're most likely getting the error because the NavigationService cannot find the resource /SecondPage.xaml. Is SecondPage located at the root of your project?
This can also be caused by trying to navigate before the target resource is loaded (for example, by navigating inside a page's constructor), but that doesn't immediately appear to be your problem.
This answer suggests that this problem can occur after changing namespaces or assembly names. It states that cleaning the project, ensuring all bin and obj folders are empty, then recompiling will fix it. However, its reference link is dead.