Xbox Live Authentication Request Returns Code "400 Bad Request" When Using Access Token Obtained Using MSAL (Swift) - msal

I am trying to authenticate with Xbox Live using an access token obtained using the MSAL authentication library for Swift.
All I am getting as a response is Response Code 400, instead of the expected JSON response containing an Xbox Live token.
I am sending the following request:
{
"Properties": {
"AuthMethod": "RPS",
"SiteName": "user.auth.xboxlive.com",
"RpsTicket": "d=(access token)"
},
"RelyingParty": "http://auth.xboxlive.com",
"TokenType": "JWT"
}
It is a POST request to https://user.auth.xboxlive.com/user/authenticate
It has these headers: Content-Type: application/json and Accept: application/json.
I am using the Swift MSAL library: https://github.com/AzureAD/microsoft-authentication-library-for-objc
My code for getting the access token looks like this:
let MSConfig = MSALPublicClientApplicationConfig(clientId: AppGlobals.clientID)
let MSApplication = try? MSALPublicClientApplication(configuration: MSConfig)
let MSScopes = ["User.Read"]
let MSWebviewParameters = MSALWebviewParameters()
let MSInteractiveParameters = MSALInteractiveTokenParameters(scopes: MSScopes, webviewParameters: MSWebviewParameters)
MSApplication?.acquireToken(with: MSInteractiveParameters, completionBlock: { (result, error) in
guard let MSAuthResult = result, error == nil else {
print("Error while authing: \(error!.localizedDescription)")
return
}
let receivedMSAccessToken = MSAuthResult.accessToken
let receivedMSAccountIdentifier = MSAuthResult.account.identifier
})
The code for obtaining an access token works as expected, and I get an access token once I log in using Microsoft. I am then using the access token obtained on line let receivedMSAccessToken = MSAuthResult.accessToken as the access token on the request line "RpsTicket": "d=(access token)". However, I am still getting error 400 (Bad Request).
What can I do to fix this?

Related

Postgraphile StatusCode: 405, ReasonPhrase: 'Method Not Allowed

I use Postgraphile locally and it work very well.
I want to send a HttpClient post requset in my Application, but it does not work and I get this error:
StatusCode: 405, ReasonPhrase: 'Method Not Allowed
hier is my code:
using (HttpClient httpClient = new HttpClient())
{
string content = "query {accounts {nodes {id,name,street,postalcode,city}}}";
var httpConent = new StringContent(content, Encoding.UTF8, "application/json");
var responseMessage = await httpClient.PostAsync("http://localhost:5000/graphiql", httpConent);
var result = responseMessage.Content.ReadAsStringAsync();
}
In line 5 of your code snippet, you're submitting to the /graphiql URL (which is for the GraphiQL GUI), you should be submitting to /graphql.
In line 4 of your snippet, you are claiming the content variable is application/json, but it is in fact a GraphQL string. You should be submitting something like {"query":"{__typename}"} as application/json.
You do not appear to be issuing an Accept: application/json header.
I suggest you use the network debugging tools of your web browser to inspect exactly what the browser is doing when it runs the GraphQL query, and compare that with what you are attempting to do with your code. You might also refer to the GraphQL-over-HTTP specification: https://graphql.github.io/graphql-over-http/draft/

Zoho desk invalid oauth

I am testing out Zoho desk API. I have set up a dummy client in zoho console dashboard and using the self client option to generate a oauth_token. However when I try to use it, it always return an error code 401 with error code "INVALID_OAUTH".
I have checked for characters, and using it before even one minute of generation. Can somebody please help me with this?
{
url = "https://desk.zoho.in/api/v1/organizations"
payload = ""
headers = {
'Authorization': "Zoho-oauthtoken 1000.XXXXXabdbd925112
4ff.44d3eccd1e1a03bd25db1016f0f13322"
}
}
Response
{
"errorCode": "INVALID_OAUTH",
"message": "The OAuth Token you provided is invalid."
}

Calling rest server from mobile app

Following on from https://lists.hyperledger.org/g/composer/message/91
I have adapted the methodology described by Caroline Church in my IOS app.
Again I can authenticate with google but still get a 401 authorization error when POSTing.
I have added the withCredentials parameter to the http header in my POST request.
does the rest server pass back the token in cookie ? I don't receive anything back from the rest server.
where does the withCredentials get the credentials from ?
COMPOSER_PROVIDERS as follows
COMPOSER_PROVIDERS='{
"google": {
"provider": "google",
"module": "passport-google-oauth2",
"clientID": "93505970627.apps.googleusercontent.com",
"clientSecret": "",
"authPath": "/auth/google",
"callbackURL": "/auth/google/callback",
"scope": "https://www.googleapis.com/auth/plus.login",
"successRedirect": "myAuth://",
"failureRedirect": "/"
}
}'
the successRedirect points back to my App. After successfully authenticating I return to the App.
Got this working now. The App first authenticates with google then exchanges the authorization code with the rest server.
The Rest server COMPOSER_PROVIDERS needs to be changed to relate back to the app.
clientID is the apps ID in google,
callbackURL and successRedirect are reversed_clientID://
The App calls http://localhost:3000/auth/google/callback with the authorization code as a parameter.
this call will fail, but an access_token cookie is written back containing the access token required for the rest server.
The user id of the logged in user is not passed back, when exchanging the code for a token with google we get back a JWT with the details of the logged in user. We need this back from the rest server as well as the token. Is there any way to get this ?
changing the COMPOSER_PROVIDERS means that the explorer interface to the Rest server no longer works.
func getRestToken(code: String) {
let tokenURL = "http://localhost:3000/auth/google/callback?code=" + code
let url = URL(string:tokenURL);
var request = URLRequest(url: url!);
request.httpMethod = "GET";
request.setValue("localhost:3000", forHTTPHeaderField: "Host");
request.setValue("text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8", forHTTPHeaderField: "Accept");
request.setValue("1", forHTTPHeaderField: "Upgrade-Insecure-Requests");
request.httpShouldHandleCookies = true;
request.httpShouldUsePipelining = true;
let session = URLSession.init(configuration: .default);
session.configuration.httpCookieAcceptPolicy = .always;
session.configuration.httpShouldSetCookies=true;
session.configuration.httpCookieStorage = HTTPCookieStorage.shared;
let task = session.dataTask(with: request) { (data, response, error) in
var authCookie: HTTPCookie? = nil;
let sharedCookieStorage = HTTPCookieStorage.shared.cookies;
// test for access_token
for cookie in sharedCookieStorage! {
if cookie.name == "access_token"
{
print(“Received access token”)
}
}
guard error == nil else {
print("HTTP request failed \(error?.localizedDescription ?? "ERROR")")
return
}
guard let response = response as? HTTPURLResponse else {
print("Non-HTTP response")
return
}
guard let data = data else {
print("HTTP response data is empty")
return
}
if response.statusCode != 200 {
// server replied with an error
let responseText: String? = String(data: data, encoding: String.Encoding.utf8)
if response.statusCode == 401 {
// "401 Unauthorized" generally indicates there is an issue with the authorization
print("Error 401");
} else {
print("HTTP: \(response.statusCode), Response: \(responseText ?? "RESPONSE_TEXT")")
}
return
}
}
task.resume()
}
have you authorised the redirect URI in your Google OAUTH2 configuration ?
This determines where the API server redirects the user, after the user completes the authorization flow. The value must exactly match one of the redirect_uri values listed for your project in the API Console. Note that the http or https scheme, case, and trailing slash ('/') must all match.
This is an example of an Angular 5 successfully using it Angular 5, httpclient ignores set cookie in post in particular the answer at the bottom
Scope controls the set of resources and operations that an access token permits. During the access-token request, your application sends one or more values in the scope parameter.
see https://developers.google.com/identity/protocols/OAuth2
The withCredentials option is set, in order to create a cookie, to pass the authentication token, to the REST server.
Finally this resource may help you https://hackernoon.com/adding-oauth2-to-mobile-android-and-ios-clients-using-the-appauth-sdk-f8562f90ecff

Post a message to slack using https://slack.com/api/chat.postMessage

I want to post a message to slack on x channel
I need to send the following x parameters
how do I send the following parameters to a website
"channel": "XXXXX",
"token": "token",
"text": "text"
Add your parameters to the end of Slack's chat.postMessage endpoint like this:
http://slack.com/api/chat.postMessage?token=XXX&channel=XXX&text=XXX
Then make a GET request to that URL to post your message. Personally I'd suggest doing this as a Node application and using the request package obtained via npm. Makes it very easy.
Post message to Slack in a Node App
Create a new node project and then change to that folder on the command line
On the command line type npm install -g request to install the request module for your project
Inside the index.js file (or wherever you plan on calling the API) do as follows:
//Import request module
var request = require('request');
//Replace your token, channelID and text here
var path_to_call = 'http://slack.com/api/chat.postMessage?token=XXX&channel=XXX&text=XXX';
request(path_to_call, function(error, response, body) {
if (!error && response.statusCode == 200) {
console.log('Success');
} else {
console.log(error);
}
});
If you just want to post messages I would recommend to use an Incoming Webhook. They are specifically designed for that purpose and easier to use than API calls.
An Incoming webhook is a custom URL that you can create for your Slack team and then use to send messages into any channel. For sending a message you only need to submit your message in JSON format along with some parameters as POST request to your webhook URL.
If you are using PHP scripting on your website then you best use CURL for the call.
Check out the documentation for details on how to use it.
var url = "https://slack.com/api/chat.postMessage";
var auth_token = auth_token; //Your Bot's auth token
var headers = {
"Authorization": "Bearer " + auth_token,
"Content-Type" : "application/json"
}
var body = {
channel: userSlackId, // Slack user or channel, where you want to send the message
text: "Your text goes here."
}
request.post({
"url": url,
"headers": headers,
"body": JSON.stringify(body)
}, (err, response, body) => {
if (err) {
reject(err);
}
console.log("response: ", JSON.stringify(response));
console.log("body: ",body);
});
You have to set headers as Authorization, and add Bearer before your token as it is mentioned in slack docs. Also, send user/channel in body. Here I'm providing the link for the same for your reference https://api.slack.com/methods/chat.postMessage#channels . Hope this helps.
Not sure which language you're using, but if using Postman to test, you can try the following format.
raw Postman request
POST /api/chat.postMessage HTTP/1.1
Host: slack.com
Content-Type: application/json
Cache-Control: no-cache
{
"text": "This is a line of text.\nAnd this is another one.",
"token": "XXXX",
"channel": "XXXX",
}

Unable to refresh access token : response is "unauthorized_client"

I am getting an error when I try to refresh access token:
400 Bad Request
{error : "unauthorized_client"}
From the Google token URI:
{
"error" : "invalid_request"
}
I read this answer here and the official Google documentation (which describes how a POST request should look) and I don't see any difference.
I captured my POST request (secrets removed):
POST /SHOWMERAWPOST HTTP/1.1
User-Agent: Google-HTTP-Java-Client/1.10.3-beta (gzip)
Pragma: no-cache
Host: requestb.in
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 175
Connection: keep-alive
Cache-Control: no-cache
Accept-Encoding: gzip
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
grant_type=refresh_token&refresh_token=******&client_id=*******.apps.googleusercontent.com&client_secret=******
Java code which sends the request:
RefreshTokenRequest req = new RefreshTokenRequest(new NetHttpTransport(), new JacksonFactory(), new GenericUrl(
getSecrets().getDetails().getTokenUri()), REFRESH_TOKEN);
req.set("client_id", getSecrets().getDetails().getClientId());
req.set("client_secret", getSecrets().getDetails().getClientSecret());
TokenResponse response = req.execute();
Is there anything wrong?
PROBLEM EXPLANATION
With the hint #MartinV gave I was finally able to fix it! Because his answer doesn't explain very well how to solve it, I'm going to post it here.
The problem is because we all have generated the Refresh Token using Google's OAuth Playground, but when you click 'Authorize APIs' in the first step, it takes you to the concent screen using the Playground app. After that, all the tokens that you create can be used only by the Playground app, but of course you don't know either the Client ID or the Client Secret for that app.
SOLUTION
The solution is to make Playground to use your own Client ID and Secret. To do so, click on the Settings button:
And enter your Client ID and Secret. But, before you do that, as it says there, you need to go to the Developer's Console, find your OAuth 2.0 client IDs client, edit it and add https://developers.google.com/oauthplayground under Authorized redirect URIs. After you added that and saved the changes, go back to the playground and try to Authorize APIs. In my case it took like 15 minutes before the changes in the Authorized redirect URIs took effect.
Once you're done, don't forget to remove the Playground URI from the Developer Console!
EXTRA
Once I have done that, in Python I did this and it worked:
access_token = None
client_id = 'xxxxxxxx.apps.googleusercontent.com'
client_secret = 'xxxxxxxxxxxx'
refresh_token = 'xxxxxxxxxxxx'
token_expiry = None
token_uri = "https://accounts.google.com/o/oauth2/token"
user_agent = 'YourAgent/1.0'
credentials = client.GoogleCredentials(access_token, client_id, client_secret, refresh_token, token_expiry, token_uri, user_agent)
http = credentials.authorize(httplib2.Http())
credentials.refresh(http)
service = build('drive', 'v3', http=http)
req = service.files().list()
resp = req.execute(http=http)
I created access and refresh token in OAuth2 playground and then i copied them to my app.
It`s not allowed to have different clients for autorization and for token refresh.
Another solution using the REST API to get an access_token and then use it to interact with the REST API (e.g. add a video to a private playlist) after creating the refresh_token as described above.
import requests
import json
# according to https://stackoverflow.com/a/41556775/3774227
client_id = '<client_id>'
client_secret = '<client_secret>'
refresh_token = '<refresh_token>'
playlist_id = '<playlist>'
video_id = 'M7FIvfx5J10'
def get_access_token(client_id, client_secret, refresh_token):
url = 'https://www.googleapis.com/oauth2/v4/token'
data = {
'client_id': client_id,
'client_secret': client_secret,
'refresh_token': refresh_token,
'grant_type': 'refresh_token'
}
response = requests.post(
url=url,
data=data,
)
return response.json().get('access_token')
def add_video_to_playlist(playlist_id, video_id, access_token):
url = 'https://www.googleapis.com/youtube/v3/playlistItems'
params = {
'part': 'snippet',
}
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer {}'.format(access_token)
}
data = {
'snippet': {
'playlistId': playlist_id,
'resourceId': {
'kind': 'youtube#video',
'videoId': video_id
},
}
}
requests.post(
url=url,
params=params,
headers=headers,
data=json.dumps(data)
)
if __name__ == '__main__':
access_token = get_access_token(client_id, client_secret, refresh_token)
add_video_to_playlist(playlist_id, video_id, access_token)
I had the same problem. The solution was to use the same client when authorizing in the application and when updating the token on the server.
Can't refresh access token for Google Calendar API on server side

Resources