My code fails for https with bad request and works for http - http-status-code-404

I have tried everything available on line but in vain. The code below works for http and not https.
I have tls 1.2 enable on my system and ssl certificate is self signed that I am using with https and using IIS web server from MS.
Also when I try to access the url from IIS Browse Website I see the same error with these details:
This error (HTTP 400 Bad Request) means that Internet Explorer was able to connect to the web server, but the webpage could not be found because of a problem with the address.
But there are no issues with the address.
I also see this error in the event viewer:
The application-specific permission settings do not grant Local Activation permission for the COM Server application with CLSID
{2593F8B9-4EAF-457C-B68A-50F6B8EA6B54}
and APPID
{15C20B67-12E7-4BB6-92BB-7AFF07997402}
to the user CORP\qahee SID (S-1-5-21-606747145-1993962763-839522115-104115) from address LocalHost (Using LRPC) running in the application container Unavailable SID (Unavailable). This security permission can be modified using the Component Services administrative tool.
Though I have changed the permission to full control in the registry for the user CORP\qahee and have rebooted the system before trying again I still get the error.
I have all three version of tls enabled in the registry and also in the internet options.
I wonder if the issue is due to self signed certificate.
Here is my code:
private string GetSessionId(string id)
{
var url
System.Configuration.ConfigurationManager.AppSettings["SessionServerURL"] ??"http://localhost";
System.Net.ServicePointManager.SecurityProtocol |=
System.Net.SecurityProtocolType.Tls12 |
System.Net.SecurityProtocolType.Tls11 |
System.Net.SecurityProtocolType.Tls;
using (var handler = new HttpClientHandler() { UseDefaultCredentials =
true })
{
handler.ServerCertificateCustomValidationCallback =
ServerCertificateCustomValidation;
using (var client = new HttpClient(handler))
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
newMediaTypeWithQualityHeaderValue("application/json"));
logger.Debug("handler: " + handler + " url: " + url +
" BaseAddress: " + client.BaseAddress);
// HTTP GET
try
{
HttpResponseMessage response =
client.GetAsync("/System/StartSession/" + id).Result;
logger.Debug("response status: " +
response.StatusCode +
" req msg: " + response.RequestMessage +
" reasonphrase:+response.ReasonPhrase);
if (response.IsSuccessStatusCode)
{
var jsonText =
response.Content.ReadAsStringAsync().Result;
var result =
JsonConvert.DeserializeObject<string>(jsonText);
return result;
}
}
This is the output for http when it runs w/o failure:
response status: OK req msg: Method: GET, RequestUri: 'http://localhost:83/System/StartSession/434f52505c7161686565', Version: 1.1, Content: , Headers:
{
Accept: application/json
} reason phrase: OK
For https this is the failure I get
response status: BadRequest req msg: Method: GET, RequestUri: 'https://abe-s19-qe1.qae.xxx.com:444/System/StartSession/434f52505c7161686565', Version: 1.1, Content: , Headers:
{
Accept: application/json
} reason phrase: Bad Request

Related

JSON error when requesting resources from Azure Graph API

I'm using the example from https://github.com/AzureAD/microsoft-authentication-library-for-python/blob/dev/sample/confidential_client_secret_sample.py. My aim is to grab the URL to report on the number emails read, sent and received by user.
I've been playing around with the endpoint setting and decided to hardcode it whilst testing. The Graph API resources is at GET https://graph.microsoft.com/v1.0/reports/getEmailActivityUserCounts(period='D7').
The code i'm using is as follows.
if "access_token" in result:
# Calling graph using the access token
graph_data = requests.get( # Use token to call downstream service
"https://graph.microsoft.com/v1.0/reports/getEmailActivityUserCounts(period=\'D7\')",
#config["endpoint"],
headers={'Authorization': 'Bearer ' + result['access_token']},).json()
print("Graph API call result: %s" % json.dumps(graph_data, indent=2))
I believe i am correctly escaping D7 but when i run the code i get the following error.
Exception has occurred: JSONDecodeError
Expecting value: line 1 column 1 (char 0)
During handling of the above exception, another exception occurred:
During handling of the above exception, another exception occurred:
To add to this, the JSON is in the format of, when i removed the string and uncommented #config["endpoint"],
{
"authority": "https://login.microsoftonline.com/XXX/",
"client_id": "XXX",
"scope": ["https://graph.microsoft.com/.default"],
"secret": "XXX",
"endpoint": "https://graph.microsoft.com/v1.0/reports/getEmailActivityUserCounts(period='D7')"
}
Is this because the JSONDecoder can't decode the escaped characters for D7?
I tried to reproduce the same in my environment and got the results successfully as below:
I created an Azure AD application and granted API Permission:
To retrieve the report on the number emails read, sent and received by user, I used the below Python code:
import requests
import urllib
import json
import csv
import os
client_id = urllib.parse.quote_plus('ClientID')
client_secret = urllib.parse.quote_plus('ClientSecret')
tenant = urllib.parse.quote_plus('TenantID')
auth_uri = 'https://login.microsoftonline.com/' + tenant \
+ '/oauth2/v2.0/token'
auth_body = 'grant_type=client_credentials&client_id=' + client_id \
+ '&client_secret=' + client_secret \
+ '&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default'
authorization = requests.post(auth_uri, data=auth_body,
headers={'Content-Type': 'application/x-www-form-urlencoded'
})
token = json.loads(authorization.content)['access_token']
graph_uri = \
'https://graph.microsoft.com/v1.0/reports/getEmailActivityUserCounts(period=%27D7%27)'
response = requests.get(graph_uri, data=auth_body,
headers={'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token})
print("response:",response.text)
I am able to get the report successfully like below:

Service account request to IAP-protected app results in 'Invalid GCIP ID token: JWT signature is invalid'

I am trying to programmatically access an IAP-protected App Engine Standard app via Python from outside of the GCP environment.
I have tried various methods, including the method shown in the docs here: https://cloud.google.com/iap/docs/authentication-howto#iap-make-request-python. Here is my code:
from google.auth.transport.requests import Request
from google.oauth2 import id_token
import requests
def make_iap_request(url, client_id, method='GET', **kwargs):
"""Makes a request to an application protected by Identity-Aware Proxy.
Args:
url: The Identity-Aware Proxy-protected URL to fetch.
client_id: The client ID used by Identity-Aware Proxy.
method: The request method to use
('GET', 'OPTIONS', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE')
**kwargs: Any of the parameters defined for the request function:
https://github.com/requests/requests/blob/master/requests/api.py
If no timeout is provided, it is set to 90 by default.
Returns:
The page body, or raises an exception if the page couldn't be retrieved.
"""
# Set the default timeout, if missing
if 'timeout' not in kwargs:
kwargs['timeout'] = 90
# Obtain an OpenID Connect (OIDC) token from metadata server or using service
# account.
open_id_connect_token = id_token.fetch_id_token(Request(), client_id)
print(f'{open_id_connect_token=}')
# Fetch the Identity-Aware Proxy-protected URL, including an
# Authorization header containing "Bearer " followed by a
# Google-issued OpenID Connect token for the service account.
resp = requests.request(
method, url,
headers={'Authorization': 'Bearer {}'.format(
open_id_connect_token)}, **kwargs)
print(f'{resp=}')
if resp.status_code == 403:
raise Exception('Service account does not have permission to '
'access the IAP-protected application.')
elif resp.status_code != 200:
raise Exception(
'Bad response from application: {!r} / {!r} / {!r}'.format(
resp.status_code, resp.headers, resp.text))
else:
return resp.text
if __name__ == '__main__':
res = make_iap_request(
'https://MYAPP.ue.r.appspot.com/',
'Client ID from IAP>App Engine app>Edit OAuth Client>Client ID'
)
print(res)
When I run it locally, I have the GOOGLE_APPLICATION_CREDENTIALS environment variable set to a local JSON credential file containing the keys for the service account I want to use. I have also tried running this in Cloud Functions so it would presumably use the metadata service to pick up the App Engine default service account (I think?).
In both cases, I am able to generate a token that appears valid. Using jwt.io, I see that it contains the expected data and the signature is valid. However, when I make a request to the app using the token, I always get this exception:
Bad response from application: 401 / {'X-Goog-IAP-Generated-Response': 'true', 'Date': 'Tue, 09 Feb 2021 19:25:43 GMT', 'Content-Type': 'text/html', 'Server': 'Google Frontend', 'Content-Length': '47', 'Alt-Svc': 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"'} / 'Invalid GCIP ID token: JWT signature is invalid'
What could I be doing wrong?
The solution to this problem is to exchange the Google Identity Token for an Identity Platform Identity Token.
The reason for the error Invalid GCIP ID token: JWT signature is invalid is caused by using a Google Identity Token which is signed by a Google RSA private key and not by a Google Identity Platform RSA private key. I overlooked GCIP in the error message, which would have told me the solution once we validated that the token was not corrupted in use.
In the question, this line of code fetches the Google Identity Token:
open_id_connect_token = id_token.fetch_id_token(Request(), client_id)
The above line of code requires that Google Cloud Application Default Credentials are setup. Example: set GOOGLE_APPLICATION_CREDENTIALS=c:\config\service-account.json
The next step is to exchange this token for an Identity Platform token:
def exchange_google_id_token_for_gcip_id_token(google_open_id_connect_token):
SIGN_IN_WITH_IDP_API = 'https://identitytoolkit.googleapis.com/v1/accounts:signInWithIdp'
API_KEY = '';
url = SIGN_IN_WITH_IDP_API + '?key=' + API_KEY;
data={
'requestUri': 'http://localhost',
'returnSecureToken': True,
'postBody':'id_token=' + google_open_id_connect_token + '&providerId=google.com'}
try:
resp = requests.post(url, data)
res = resp.json()
if 'error' in res:
print("Error: {}".format(res['error']['message']))
exit(1)
# print(res)
return res['idToken']
except Exception as ex:
print("Exception: {}".format(ex))
exit(1)
The API Key can be found in the Google Cloud Console -> Identity Platform. Top right "Application Setup Details". This will show the apiKey and authDomain.
More information can be found at this link:
Exchanging a Google token for an Identity Platform token

how to fix '403 (Forbidden)' on a $http.get request to etherpad

[header][1]
[header][2]
i am trying to send a get request to etherpad hosted in a different domain. the OPTIONS preflight request goes through but the get request returns 403 status.
however when i install CORS for chrome extension the request goes through
when i install cors chrome extension the request goes through
here is my code:
/* ........ export draft to html/pdf/word ........ */
//get content for this template
var url = Drafting.domain + Drafting.port + '/p/' + Drafting.padID + '/export/html?' + 'apikey=' + Drafting.apikey;
$http.get(url).then(function(response, status){
if(typeof(callback)==='function' && callback)
{
callback(response.data);
}
});
```}
[1]: https://i.stack.imgur.com/25dsj.png
[2]: https://i.stack.imgur.com/ivHnn.png
i just passed 'withCredentials:true' together with the url and then modified the importexport.js inside the etherpad files where 'AccessControlAllowOrigin' was set to '*' i replaced it with a specific domain and it worked.

angular-sails websocket url undefined ( ws://www.undefined)

I am using sails 0.10.5 and in angular frontend with angular-sails .
It gives an error like below on server side Whenever an api call by $sails.get
In My FrontEnd side controller code :
io.sails.url = 'http://localhost:1337';
io.socket.get('http://localhost:1337/admin/v1/user/subscribe', function (body, response) {
console.log('Sails responded with: ', body);
console.log('with headers: ', response.headers);
console.log('and with status code: ', response.statusCode);
});
and console is
Sails responded with: Object {}
app.js:167 with headers: Object {}
app.js:168 and with status code: 200
But in backend side sails console gives error like this
debug: --------------------------------------------------------
debug: :: Fri Dec 19 2014 10:44:25 GMT+0530 (India Standard Time)
debug: Environment : development
debug: Port : 1337
debug: --------------------------------------------------------
error: Error:
res.redirect() :: [socket.io] ::
Cannot redirect socket to invalid location :: 'ws://www.undefinedhttp://localhost:1337/admin/v1/user/subscribe'
at Object.Err.invalidRedirect (C:\wamp\www\i-phone\i-phone\node_modules\sails\lib\hooks\sockets\lib\interpreter\interpret.js:33:14)
at ResStream.doRedirect (C:\wamp\www\i-phone\i-phone\node_modules\sails\lib\hooks\sockets\lib\interpreter\interpret.js:310:31)
at C:\wamp\www\i-phone\i-phone\node_modules\sails\lib\hooks\sockets\lib\interpreter\saveSessionAndThen.js:23:7
at C:\wamp\www\i-phone\i-phone\node_modules\sails\lib\hooks\session\index.js:59:17
My route file is like this :
'get /admin/v1/user/subscribe': 'UserController.subscribe',
And in UserController.js :
subscribe: function (req, res) {
console.log('aaaaaaaaaaaaaaaaaaaa')
User.find().exec(function(err,users){
// subscribing this socket to User model classroom
User.subscribe(req.socket);
// subscribing this socket to User model instance room
User.subscribe(req.socket,users);
console.log('subscribe')
})
}
For setting up Socket connection with server:
Include sails.io.js in index.html.
Create a global variable for io.sails.url and you'll need to tell the Sails socket client what URL to connect to:
io.sails.url = 'http://localhost:1337';
Put this anywhere before you start making socket calls; the library is smart enough to wait until its connected before trying to make the calls.
To Check if Socket is connected,
io.socket.get('http://localhost:1337/data', function (body, response) {
console.log('Sails responded with: ', body);
console.log('with headers: ', sailsResponseObject.headers);
console.log('and with status code: ', sailsResponseObject.statusCode);
});
You should be able to see in the console whether or not the socket connected by looking for the "io.socket connected successfully." message.
The above code was about setting up socket connection as you requested.
Regarding your problem, Can you please provide some Code
The controller action you posted is clearly not being run (you would see the aaaaaaaaaaaaaaaaaaaa log in your console). Some other code is running and is calling res.redirect with invalid arguments. My first guess would be that you have a policy configured in config/policies.js that is attached to the UserController.subscribe action.
It was little silly mistake.
In my route.js , I am redirecting non WWW request to WWW request .
And socket request start with ws:// tag , thats why it is being also redirect to www.undefined
It is solved by a small condition
if(!req.isSocket){
// redirect logic
}else{
next();
}

Angular Digest Authentication

I'm trying to connect to a RESTFul API on a home automation server in my house (so massive security not required). When I try to connect with no credentials, I get:
[Error] XMLHttpRequest cannot load http://localhost:8176/devices/. Origin http://localhost is not allowed by Access-Control-Allow-Origin.
The documentation says:
Indigo uses "digest authentificaction" (not basic nor token)
curl -X PUT --digest -u {username}:{password} -d value={value} http://{IPAddress}:8176/variables/{VariableToChange}
curl -X PUT --digest -u admin:p#ssw0rd -d value=true http://{IPAddress}:8176/variables/Var1
To get a list of devices, I can use one of these 3:
http://127.0.0.1:8176/devices/
http://127.0.0.1:8176/devices.xml/
http://127.0.0.1:8176/devices.txt/
I'm at a total loss on how to pass the creeds. Here's my code so far:
function DeviceController($scope, $http) {
$http.get("http://localhost:8176/devices/")
.then(function (results) {
//Success;
console.log("Succss: " + results.status);
$scope.devices = results.data;
}, function (results) {
//error
console.log("Error: " + results.data + "; "
+ results.status);
$scope.error = results.data;
})
};
Can anyone point me in right direction?
Thanks
Mark
Your server has to be configured to accept CORS (Cross-origin resource sharing).
EDIT:
It looks like your Indigo (don't know what it is) server is not the one serving your angular app. Please refer to your server's documentation on how to enable CORS.
As far as passing your credentials during your request, do:
$http({
method: "GET",
url: "http://localhost:8176/devices/",
headers: {"Authorization": "Basic " + btoa("admin:p#ssw0rd")},
})...

Resources