OAuth2 Session - How to add multiple scopes? - scopes

I am trying to add multiple scopes but it seems instead of adding spaces in the url, it adds +. I'm not sure how to ensure a space is added. I'm storing the scopes in a list.
CALLBACK_URL = 'https://localhost/callback'
CLIENT_SECRET = SETTINGS['client_secret']
CLIENT_SCOPES = ['esi-mail.organize_mail.v1 ', 'esi-mail.send_mail.v1 ', 'esi-assets.read_assets.v1 ',
'esi-characters.read_blueprints.v1 ', 'esi-assets.read_corporation_assets.v1 ',
'esi-corporations.read_blueprints.v1 ']
ENDPOINT = 'https://login.eveonline.com/oauth/authorize'
def oauth_session(client_id, client_secret, scopes):
client = OAuth2Session(client_id, client_secret, scope=scopes)
uri, state = client.create_authorization_url(ENDPOINT)
return uri, state
The response shows the following as scopes (just scopes for brevity):
&scope=esi-mail.organize_mail.v1++esi-mail.send_mail.v1++esi-assets.read_assets.v1++esi-characters.read_blueprints.v1++esi-assets.read_corporation_assets.v1++esi-corporations.read_blueprints.v1+
Am I using the wrong data structure, or there is something I am missing?

Turns out the problem was not the format of the scope at all - I was missing a redirect_uri that was required for the API I am using.

Related

DocuSign.eSign.Client.ApiException {"error":"consent_required"}" / Response Type Not Supported when attempting to grant consent

I tried to receive a token with the code below. Unfortunatelly I get the error:
DocuSign.eSign.Client.ApiException
HResult=0x80131500
Nachricht = Error while requesting server, received a non successful HTTP code with response Body: {"error":"consent_required"}
I tried with set TLS 12 and without. We run it in dev mode with base path https://demo.docusign.net/restapi
and oAuthBasePath =account-d.docusign.com
I tried also to set the consens manually with the URL below. But I receive the error in (Login Window) invalid Authorization: RequestType is not supported.
https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature%20impersonation&client_id=a5ed47d5-xxxx-xxxx-8a19-756da64391de&redirect_uri=https://www.docusign.com
Is the something wrong with my account setting?
byte[] privateKey=DSHelper.ReadFileContent(DSHelper.PrepareFullPrivateKeyFilePath(privateKeyFilename));
var scopes = new List<string>
{
"signature",
"impersonation",
};
var basePath = ApiClient.Production_REST_BasePath;
var oAuthBasePath = OAuth.Production_OAuth_BasePath;
if (!production)
{
basePath = ApiClient.Demo_REST_BasePath;
oAuthBasePath = OAuth.Demo_OAuth_BasePath;
}
var _apiClient = new ApiClient(basePath);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var authToken = _apiClient.RequestJWTUserToken(
clientId,
ImpersonatedUserId,
oAuthBasePath,
privateKey,
1,
scopes);
I found the solution. instead of reponse_type= code I have to use token
What response_type is supported for an integration key depends on how the key is configured. In the Authentication section of the key's configuration panel, Auth Code Grant allows the response type of code, while Implicit Grant allows the response type of token.
DocuSign's authentication docs assume you have "Auth Code Grant" selected, but either is technically acceptable to allow JWT consent.

Concatenate strings in flutter adds ""

This is rather a silly question but I can't seem to figure it out. I'm building a flutter app that communicates to an API and in order for the user to be authenticated it sends an token.
Whenever the user logs in I save the token in the Shared Preferences and then when I make an request add the token to the headers or in this case I need it in the url.
However, whenever I concatenate the strings: the server url and the token it adds extra "" to the token. something like:
http://10.0.2.2:64342/chatHub?access_token="token-value"
instead of
http://10.0.2.2:64342/chatHub?access_token=token-value
here's the code:
var preferences = await SharedPreferences.getInstance();
token = preferences.getString(token_key);
var url = '$serverURl?access_token=$token';
As far as I understand your question, I would like to answer it.
That's not possible!
var serverURl = 'http://10.0.2.2:64342/chatHub';
var token = 'token-value';
var url = '$serverURl?access_token=$token';
print(url);
It just prints the correct one!
You can check the string that is stored in the SharedPreferences! That maybe with quotes.
Okay, I figured it out. Since I was sending only the token from the API. I was receiving it with the "" in it.
Instead I now send a json with the token, like: { "token": "token_value"} and then decode it to get the actual value. So when I store it the shared preferences it doesn't keep the "".
So in the backend:
return Ok(new {token = generatedToken});
and in dart
var tokenJson = json.decode(response.body);
var token = tokenJson['token'];
preferences.setString(token_key, token);
Thanks to everyone that helped :)

Google Sign-In: backend verification

I have Google Sign-in working on my app: the relevant code is roughly:
var acc = await signInService.signIn();
var auth = await acc.authentication;
var token = auth.idToken;
This gives me a nice long token, which I then pass to my backend with an HTTP POST (this is working fine), and then try to verify. I have the same google-services.json file in my flutter tree and on the backend server (which is nodejs/restify). The backend code is roughly:
let creds = require('./google-services.json');
let auth = require('google-auth-library').OAuth2Client;
let client = new auth(creds.client[0].oauth_client[0].client_id);
. . .
let ticket = await client.verifyIdToken({
idToken: token,
audience: creds.client[0].oauth_client[0].client_id
});
let payload = ticket.getPayload();
This consistently returns my the error "Wrong recipient, payload audience != requiredAudience".
I have also tried registering separately with GCP console and using those keys/client_id instead, but same result. Where can I find the valid client_id that will properly verify this token?
The problem here is the client_id that is being used to create an OAuth2Client and the client_id being used as the audience in the verifyIdToken is the same. The client_id for the audience should be the client_id that was used in your frontend application to get the id_token.
Below is sample code from Google documentation.
const {OAuth2Client} = require('google-auth-library');
const client = new OAuth2Client(CLIENT_ID);
async function verify() {
const ticket = await client.verifyIdToken({
idToken: token,
audience: CLIENT_ID, // Specify the CLIENT_ID of the app that accesses the backend
// Or, if multiple clients access the backend:
//[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]
});
const payload = ticket.getPayload();
const userid = payload['sub'];
// If request specified a G Suite domain:
//const domain = payload['hd'];
}
verify().catch(console.error);
And here is the link for the documentation.
Hope this helps.
Another quick solution might be change the name of your param "audience" to "requiredAudience". It works to me. If you copied the code from google, maybe the google documentation is outdated.
client.verifyIdToken({
idToken,
requiredAudience: GOOGLE_CLIENT_ID, // Specify the CLIENT_ID of the app that accesses the backend
// Or, if multiple clients access the backend:
//[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]
});
It has already been mentioned above that requiredAudience works instead of audience, but I noticed requiredAudience works for both {client_id : <CLIENT_ID>} and <CLIENT_ID>. So maybe you were referencing creds.client[0].oauth_client[0] instead of creds.client[0].oauth_client[0].client_id? I have not been able to find any docs on the difference between requiredAudience and audience, however make sure you are sending just the <CLIENT_ID> instead of {client_id : <CLIENT_ID>}.
Google doc: link
verifyIdToken()'s call signature doesn't require the audience parameter. That's also stated in the changelog. So you can skip it, and it'll work. The documentation is kinda misleading on that.
It's also the reason why using requiredAudience works because it actually isn't being used by the method, so it's the same as not providing it.
I've been faceing this issue with google-auth-library version 8.7.0 and came across a workaround only if you have a single CLIENT_ID to verify.
Once you create your OAuth2Client like this:
const googleClient = new OAuth2Client(process.env.GOOGLE_CLIENT_ID);
You don't need to pass the CLIENT_ID in verifyIdToken function as it uses your googleClient object to create auth url.

How to use Basic Auth with libsoup via Gjs

I'm trying to query github's api with a token. Github's api accepts generated tokens provided that they're sent as a basic auth header.
The API do not return HTTP 401 if the call is made without auth which means if one wants to query their api using Basic Auth, one must fill the header pre-emptively rather than doing a round trip.
I'm now trying to query the API using libsoup and Gjs.
I have noticed the SoupAuthManager has a function that seems to match perfectly what I need (soup_auth_manager_use_auth here) but can't find a way to invoke it.
This can be used to "preload" manager 's auth cache, to avoid an extra HTTP round trip in the case where you know ahead of time that a 401 response will be returned
This is what I currently use, but it does not work as the SoupAuthManager is a private object of the session; and has therefore no effect on the actual behaviour of the program
let httpSession = new Soup.Session();
let authUri = new Soup.URI(url);
authUri.set_user(this.handle);
authUri.set_password(this.token);
let message = new Soup.Message({method: 'GET', uri: authUri});
let authManager = new Soup.AuthManager();
let auth = new Soup.AuthBasic({host: 'api.github.com', realm: 'Github Api'});
authManager.use_auth(authUri, auth);
httpSession.queue_message(message, ...);
Are there other methods I could use to force Basic Auth on the first roud trip? or are there other library I could use from gjs to call github's API and force the basic auth?
I found the solution. To link the authorisation to the session, one can use the add_feature function. Now this is defined here but it turns out calling it directly doesn't work
this._httpSession.add_feature(authManager)
instead it seems to work if called like that:
Soup.Session.prototype.add_feature.call(httpSession, authManager);
finally, the github api rejects any call without a user agent, so I added the following:
httpSession.user_agent = 'blah'
the final code looks like:
let httpSession = new Soup.Session();
httpSession.user_agent = 'blah'
let authUri = new Soup.URI(url);
authUri.set_user(this.handle);
authUri.set_password(this.token);
let message = new Soup.Message({method: 'GET', uri: authUri});
let authManager = new Soup.AuthManager();
let auth = new Soup.AuthBasic({host: 'api.github.com', realm: 'Github Api'});
Soup.Session.prototype.add_feature.call(httpSession, authManager);
httpSession.queue_message(message, function() {...});

Using APIServiceSoapClient for DocuSign

Im tring to user the DocuSign api/sdk to send a document for someone to sign. The examples say something like:
//.NET
APIServiceSoapClient apiService = new APIServiceSoapClient();
apiService.ClientCredentials.UserName.UserName = "Your DocuSign UserName here";
apiService.ClientCredentials.UserName.Password = "Your DocuSign Password here";
Which I of course have tried but its not working.
I get the following error:
Security requirements are not satisfied because the security header is not present in the incoming message.
Ive tried
var username = "myemail";
var pass = "mypass";
var iteratorKey = "iteratorkey";
APIServiceSoapClient apiService = new APIServiceSoapClient();
apiService.ClientCredentials.UserName.UserName = username;
//also tried ...UserName = "[" + iteratorKey + "]" + username;
apiService.ClientCredentials.UserName.Password = pass;
Is this not where all security requirements are met? maybe? Using APIService not DSAPIService if that makes a difference.
I ended up having to use a different way to pass in the credentials. Which I found somewhere else. Im still not sure how to correctly use the other method I tried though so if anyone knows how to use the other method it would be great just because the code is neater and easier to follow.
string auth = #"<DocuSignCredentials>
<Username>email</Username>
<Password>pass</Password>
<IntegratorKey>key</IntegratorKey>
</DocuSignCredentials>";
DSAPIServiceSoapClient apiService = new DSAPIServiceSoapClient();
using (var scope = new System.ServiceModel.OperationContextScope(apiService.InnerChannel))
{
var httpRequestProperty = new System.ServiceModel.Channels.HttpRequestMessageProperty();
httpRequestProperty.Headers.Add("X-DocuSign-Authentication", auth);
System.ServiceModel.OperationContext.Current.OutgoingMessageProperties[System.ServiceModel.Channels.HttpRequestMessageProperty.Name] = httpRequestProperty;
EnvelopeStatus envStatus = apiService.CreateAndSendEnvelope(envelope);
return envStatus.EnvelopeID;
}
There are two ways to pass member credentials through DocuSign's SOAP API (as opposed to the newer REST API):
SOAP Header via WS-Security UsernameToken
HTTP Header via a custom field “X-DocuSign-Authentication”
The Account Management API only supports the HTTP Header authentication method, while all others can support either method.
Additionally, the DocuSign SOAP API has two API end points: API.asmx and DSAPI.asmx. The API.asmx end point requires the WS-Security UsernameToken in the SOAP header authentication. The DSAPI.asmx and AccountManagement.asmx end points require the HTTP Header authentication method.

Resources