how can I get the consumer key, Signature and consumer secret(dynamically) from the server(OAuth1). So, that I can pass it in Headers->Authorization to execute my routes(register) in Postman.
I was able to get consumer key and Signature by registering client by making POST request at {{url}}/api/client/register
Sent the following code in the Body:
{
"type": "client_associate",
"application_name": "Your Application Name",
"application_type": "web"
}
Related
Been at this for a week: every, single, day. Nothing is working.
How hard is it for a minimal authentication? I bet so many people are looking for this answer too.
Here is rough-draft of what we've got so far:
import cbpro, hmac, hashlib, time,
api_key = "[YOUR_API_KEY]"
secret_key = "[YOUR_B64SECRET]"
passphrase = "[YOUR_PASSPHRASE]"
message = message.encode('ascii')
hmac_key = base64.b64decode(secret_key)
signature = hmac.new(hmac_key, message, hashlib.sha256)
signature_b64 = base64.b64encode(signature.digest()).decode('utf-8')
auth_client = cbpro.AuthenticatedClient(api_key, signature_b64, passphrase)
auth_client.get_accounts()
or while subscribing with websockets, something with this:
{
"type": "subscribe",
"product_ids": [
"BTC-USD"
],
"channels": ["full"],
"signature": "...",
"key": "...",
"passphrase": "...",
"timestamp": "..."
}
using:
socket = "wss://ws-feed.pro.coinbase.com"
ws = websocket.WebSocketApp(socket, on_open=on_open, on_message=on_message)
ws.run_forever()
I dont understand why a simply few lines of code to authenticate and view open orders/account is so hard, while subscribing to the websocket ticker and receiving price changes is so easy. Encoding the secret key shouldnt be too hard? Please help us with a super short and simple example (without all the "init"s and imports and different functions with passing). Sheesh
"I dont understand why a simply few lines of code to authenticate and view open orders/account is so hard, while subscribing to the websocket ticker and receiving price changes is so easy."
This is because your code will not produce an authenticated websockets session. The session is secured using 'wss' aka TLS, but inside of this session, you are not authenticated to their server and therefore you do not receive enhanced data elements for trade messages in which your account is involved. Receiving price data does not require being authenticated.
This is just like you are visiting a website at its "https" address, but are not logged in. "Public" data is being sent to you across a secure connection.
The cbpro module creates an AuthenticatedClient instance by passing to it the unaltered api key, base64-encoded secret, and passphrase. You should really review any module's code base before trusting it with your authentication data, or even installing it on your machine, but to each their own.
import cbpro #, hmac, hashlib, time,
api_key = YOUR_API_KEY
secret_key = YOUR_B64SECRET
passphrase = YOUR_PASSPHRASE
# message = message.encode('ascii')
# hmac_key = base64.b64decode(secret_key)
# signature = hmac.new(hmac_key, message, hashlib.sha256)
# signature_b64 = base64.b64encode(signature.digest()).decode('utf-8')
auth_client = cbpro.AuthenticatedClient(api_key, secret_key, passphrase)
auth_client.get_accounts()
You can test out what I am saying about how your websocket code is not properly authenticating either by running your wss client and subscribing to only the "user" channel for a product before placing a trade in for that product. With no other channels subscribed, you will receive a message indicating that the server received your new order. You can then cancel the order after testing. If your code does somehow allow you to receive messages in the "user" channel, then CoinbasePro is doing something different from what is published in its documentation.
when sending push messages through fcm (through nodejs firebase admin sdk), getting this error structure:
{
"results": [
{
"error": {
"code": "messaging/invalid-registration-token",
"message": "Invalid registration token provided. Make sure it matches the registration token the client app receives from registering with FCM."
}
}
],
"canonicalRegistrationTokenCount": 0,
"failureCount": 1,
"successCount": 0,
"multicastId": SOME_ID
}
Is the index of the results relates to the index of the token array that was sent to firebase?
Yes, as described here:
results Array of objects representing the status of the messages processed. The objects are listed in the same order as the request (i.e., for each registration ID in the request, its result is listed in the same index in the response).
This question is actually a continuous question of this SO question of mine. I am trying to get access_token and id_token from Identityserver4 by using Authorization code flow.
But, If I try to access "Authorize" endpoint, I got 405 (method not allowed) HTTP error.
HTTP GET Request
http://localhost:2000/connect/authorize?
client_id=client
&client_secret=secret
&grant_type=authorization_code
&username=admin
&password=admin
&response_type=id_token+token
&scope=openid+profile+offline_access
Client:
new Client
{
ClientId = "client",
ClientSecrets = { new Secret("secret".Sha256())},
AllowedGrantTypes = new List<string> { "authorization_code" },
AccessTokenType = AccessTokenType.Jwt,
AllowedScopes = { StandardScopes.OpenId.Name, "api1" }
}
User:
new InMemoryUser
{
Subject = "1",
Username = "admin",
Password = "admin"
}
My question is, How to call authorize endpoint to get access_token and id_token? What's wrong in my "client" and "user" configuration?
Two ideas:
The HTTP 405 error can be due to the web browser's same origin policy. Your client looks like a confidential client not a browser-based client, though, and that means the same origin policy does not apply, unless you are mistakenly making that request through a web browser.
That HTTP 405 error can also happen when you use an HTTP verb that is not allowed. For instance, if you use a POST when the URL allows only a GET. Make 100% sure that you are making a GET request.
You have several issues. You are mixing up multiple flows.
1) If you want to get an id_token back from the Authorize endpoint (and not the Token endpoint) you need to use Hybrid flow... not authorization code flow. See here. So you'd need to change your response type accordingly. If your client was a SPA you could use implicit flow and get an id_token and access_token from the Authorize endpoint - but not authorization code flow.
2) client_secret is not a parameter for the Authorize endpoint. Neither is grant_type. See here for the valid parameters.
3) you don't send username and password to the Authorize endpoint under any circumstances. If you are using resource owner flow you'd send them to the Token endpoint - but never Authorize. See the above link with the description of valid parameters.
So you can switch to hybrid flow and change your code to this:
http://localhost:2000/connect/authorize?
client_id=client
&redirect_uri=<add redirect uri>
&response_type=code+id_token+token
&scope=openid+profile+api1
&state=...
The response from this call will include id_token and access_token.
new Client
{
ClientId = "client",
ClientName = "Your Client",
AllowedGrantTypes = GrantTypes.Hybrid,
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = { "<add redirect uri>" },
PostLogoutRedirectUris = { "<add post logout redirect uri>" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1"
}
};
I am trying to use JWT token to access a Stream feed but it is returning 404 everytime.
Token header:
{
"alg": "HS256"
}
Token payload:
{
"resource": "feed",
"action": "read"
}
The token was generated using the jjwt library and signed using the secret provided in my account dashboard. I also validated it on jwt.io and it was a valid token
Url
GET: https://api.getstream.io/api/v1.0/feed/notification/666?api-key=...
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJyZXNvdXJjZSI6ImZlZWQiLCJhY3Rpb24iOiJyZWFkIn0.MUZHXQg0UD6jFpCZN5Mn1e7wwys_1qYuVtfBKtHL8QU
Response
{
"exception": "GetStreamAPI404",
"detail": "sorry you've hit a 404"
}
Am I missing something here? Can't figure out what the problem is.
In order to perform correct permission checking, you need to include the feed_id field in your token payload. The value of the field must be the same as the feed that you are trying to read and be in the form of ${feed_group}:${feed_id}.
For instance, the payload for the request in your question (https://api.getstream.io/api/v1.0/feed/notification/666?api-key=) should be:
{
"resource": "feed",
"action": "read",
"feed_id": "notification:666"
}
Note: API URLs must end with a trailing slash (eg. /api/v1.0/feed/notification/666/?api_key=...)
Auth HTTP headers:
Authorization must only contain the JWT token
stream-auth-type must be sent with the value jwt
I'm working on authentication for my JSON-RPC API and my current working strategy is using signed requests sent via POST over SSL.
I'm wondering if anyone can see any vulnerabilities that I haven't taken into consideration with the following signature method.
All communication between the client and the server is done via POST requests sent over SSL. Insecure http requests are denied outright by the API server.
Dependencies
var uuid = require('node-uuid');
var crypto = require('crypto');
var moment = require('moment');
var MyAPI = require('request-json').newClient('https://api.myappdomain.com');
Dependency Links: node-uuid, crypto, moment, request-json
Vars
var apiVersion = '1.0';
var publicKey = 'MY_PUBLIC_KEY_UUID';
var secretKey = 'MY_SECRET_KEY_UUID';
Request Object
var request = {
requestID : uuid.v4(),
apiVersion : apiVersion,
nonce : uuid.v4(),
timestamp : moment.utc( new Date() ),
params : params
}
Signature
var signature = crypto.createHmac('sha512',secretKey).update(JSON.stringify(request)).digest('hex');
Payload Packaging (Sent as cleartext via POST over SSL)
var payload = {
request: request,
publicKey : publicKey,
signature : signature
}
Resultant Payload JSON Document
{
"request" : {
"requestID" : "687de6b4-bb02-4d2c-8d3a-adeacd2d183e",
"apiVersion" : "1.0",
"nonce" : "eb7e4171-9e23-408a-aa2b-cd437a78af22",
"timestamp" : "2014-05-23T01:36:52.225Z",
"params" : {
"class" : "User"
"method" : "getProfile",
"data" : {
"id" : "SOME_USER_ID"
}
}
},
"publicKey" : "PUBLIC_KEY",
"signature" : "7e0a06b560220c24f8eefda1fda792e428abb0057998d5925cf77563a20ec7b645dacdf96da3fc57e1918950719a7da70a042b44eb27eabc889adef95ea994d1",
}
POST Request
MyAPI.post('/', payload, function(response){
/// Handle any errors ...
/// Do something with the result ...
/// Inspect the request you sent ...
});
Server-Side
And then on the server-side the following occurs to authenticate the request:
PUBLIC_KEY is used to lookup the SECRET_KEY in the DB.
SECRET_KEY is used to create an HMAC of the request object from the payload.
The signature hash sent in the payload is compared to the hash of the request object created on the server. If they match, we move on to authenticating the timestamp.
Given that we can now trust the timestamp sent in the cleartext request object since it was included in the signature hash sent from the client, the timestamp is evaluated and the authentication is rejected if the request is too old. Otherwise, the request is authenticated.
So far as I understand, this is a secure method for signing and authentication requests sent over SSL. Is this correct?
Thanks in advance for any help.
Update on JSON Property Order
The order of properties when using JSON.stringify is essentially random, which could cause signature mis-matches.
Using this signing process over the past few weeks I haven't run into any hash mis-match issues due to the order of the properties in the JSON request object. I believe it's because I only stringify the request object literal once, right before the client-side hash is calculated. Then, the request object is in JSON format as part of the payload. Once received by the server, the hash is created directly from the JSON object received in the payload, there's no second JSON.stringify method invoked, so the signature always matches because the order of the properties is determined once, by the client. I'll keep looking into this though as it seems like a weak point, if not a security concern.
JSON.stringify does not guarantee order of properties. For example, object
{
a: 1,
b: 2
}
could be serialized in two ways: {"a":1,"b":2} or {"b":2,"a":1}. They are the same from JSON point of view but they will result it different HMACs.
Imaging, that for signings your JSON.stringify produced first form, but for checking signature second one. Your signature check will fail although signature was valid.
The only fishy thing I see here would be the JSON.stringify as posted in other comments, but you can use:
https://www.npmjs.com/package/json-stable-stringify
That way you can have a deterministic hash for you signs.