Sails disable criteria for REST in GET - rest

I have implemented passport-local strategy and passport-bearer strategy.
When user logins with username/password credentials, I generate JSON Web Token which returns to requester. On each request I get access_token from query, decode this token from JWT to object and make bearer authorization implemented in /api/policies. And all auth works fine.
But when I provide this access_token to RESTful route i.e. user I got empty array.
The problem, that Sails accepts access_token as criteria.
Example:
GET /user ## Forbidden
GET /user?access_token=<token> ## Empty array
How can I disable or fix it?

You would probably be better off sending your access token in a header than in the URL. But if what your asking is how to blacklist a certain property from being used as criteria in a blueprint route, it can be done in the following way in your config/routes.js file:
"GET /user": {blueprint: "find", criteria: {blacklist: ["access_token"]}}
This will override the default blacklist, so you may want to include those defaults in your custom array:
"GET /user": {
blueprint: "find",
criteria: {
blacklist: ["access_token", "limit", "skip", "sort", "populate"]
}
}

Related

Using OAuth2 how do I pull the access token into a variable?

I am trying to make a call to an authorization endpoint using OAuth2 with grant type Client Credentials - my call is successful - that is not an issue. However, I, now, want to take the access token that is returned and put it in a variable so I may use it in subsequent calls without having to manually cut-and-paste to my other calls.
When the call returns I see the token I desire to copy in the Access Token field at the bottom of the OAuth2 window (the one shown below that says expires in 42 minutes) AND I see it in the Authorization field on the Timeline tab of the results. I just can't figure out how to get access to it so I may dump it into variable.
The gif on the FAQ goes really fast, and does not provide step by step. Also, I didnt find any answer on YouTube or other websites, so I thought to share step by step for chaining requests on Insomnia.
Create a POST query to obtain your access token. Notice that my access token is returned in the field called "access_token", we will use this in step 3. Your return field may be different.
Create a second GET request for the API that would return the data for you. In my case, I wanted to get all users from a SCIM interface. In the Bearer tab, type in Response => Body Attribute (Insomnia will autofill).
Mouse click on the Request => Body Attribute (the one you just typed in), and select the authentication post in the dropdown "Request" (this is the one you created in step 1), and in the "Filter (JSONPath)" field, type in the $.[attribute name] - where attribute name is the response that returns from authentication call. In my case, it was access_token, see step 1 for yours.
Enjoy!!
Click No Environment > Manage Environments and you will see a base environment in JSON.
Since this is in JSON, create a { "jwt_token": "Response => Body Attribute" }" pair for your token variable. Please note that "Response => Body Attribute" needs to be configured. When you type response, hit space and this option should be available.
Once done choosing "Response => Body Attribute", it will show with some gibberish content and with red background, no worries... just click it to configure. Make sure you have the same setup.
However... you need to change your request to the route where you get the token from the server and another thing is the Filter (JSONPath or XPath) change it depending on your setup.
You should have the token, stored in jwt_token variable and can use the variable on a route that you like.
Example:
If you want to save a token that is returned in a response into an environment variable, you can use request chaining in your environment variable. Take a look at this url for more details on that https://support.insomnia.rest/article/43-chaining-requests...
Here is what you could do (what I did)
Create an environment variable
For the value of the variable, use the Response => Body Attribute and under Filter (JSONPath or XPath), choose the attribute of the token in your response body (if it is "token" then put $.token).
After that just put the token environment variable wherever you need it in the following requests.
I was not able to resolve this question but was able to get around it by defining the fields in the body of the request and bypassing the OAuth2 tab completely.
You can add it as a header, by referencing the outputs of the OAuth2 request:

Please guide me about my Yii2 code about RESTFul authentication by token

I have been look around google whole day and still not getting idea how to achieve RESTFul httpBasicAuth by using token.
First, I would like to ask can i using RESTFul HttpBasicAuth without Https ?
Then, below is my code to try to do Yii2 RESTFul HttpBasicAuth authenticaton, hope someone can spend some time review on my code and guide me what wrong on my code.
First this is my yii2 config setting about User Application component:
'user' => ['identityClass' => 'common\models\Users',
'enableAutoLogin' => false
],
then below is snippet of my common\models\Users IdentityClass
namespace common\models;
use Yii;
use yii\base\NotSupportedException;
use yii\web\IdentityInterface;
use app\models\Ostoken;
class Users extends \yii\db\ActiveRecord implements IdentityInterface
{
public static function findIdentityByAccessToken($token, $type = null) {
/* Compulsory for RESTFul*/
// die("trying...");
// throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
file_put_contents("/var/www/html/y2api/logs/RESTFul_login_".date("Y-m-d"), date("H:i:s").":".$token."\r\n", FILE_APPEND);
$apiUser = Ostoken::find()
->where(['token' => $token])
->one();
return static::findOne(['username' => $apiUser->username]);
}
}
then I try to call the restful URL by http://192.168.33.10/api/Banktransactions?access-token=xxxxxxxx
then i get following error in json format :
{
"name": "Unauthorized",
"message": "Your request was made with invalid credentials.",
"code": 0,
"status": 401,
"type": "yii\\web\\UnauthorizedHttpException"
}
as you can see I put a file_put_contents in findIdentityByAccessToken but it never execute.
First question:
First, I would like to ask can i using RESTFul HttpBasicAuth without Https ?
Answer: You can, but:
Since an access token can be used to uniquely identify and authenticate a user, API requests should always be sent via HTTPS to prevent man-in-the-middle (MitM) attacks. (https://www.yiiframework.com/doc/guide/2.0/en/rest-authentication#authentication)
Second...question?:
I'm 100% sure this is because CORS.
Check out this:
https://www.yiiframework.com/doc/api/2.0/yii-filters-cors
Ever tried to reach the url through localhost? If so and it worked then you need to set up a CORS filter to be able to make a request to your server.

Identity server3 : User Info endpoint returns null Claims

I am using Authorization Code flow and I am trying to get the user information using user info endpoint, but I am not getting claims. I've enabled IncludeInIdToken for some claims like name profile email and when decode Idtoken I was not able to see the above claims.
I've tried by debugging the method GetProfileDataAsync, here I found the "Name" property coming null, since I am using the AD group I need this Name property here.
I tried to save "Name" into global variable in LocalLoginAsync method and used the same in GetProfileDataAsync method. Now I have added claims to the TaskResult, but I am getting count '0' in the response
When I request for tokens by using code I am able to see the following result in Claims
and I am not able to see those claims in IdToken,
Next, time when request using user info endpoint by using access token I am not getting any Claim except "sub" or no Name property.
How can I get Claim with User Info endpoint response
I've tried by debugging the code and found the issue, since I am doing the mistake like
return Task.FormResult(identity.Claims.where(x=>context.RequestedClaimTypes.Contains(x.Types)));
instead of doing
context.IssuedClaims = identity.Claims.where(x=>context.RequestedClaimTypes.Contains(x.Types));
return Task.FromResult(0);
But still I am getting the username(Name) property null with user info endpoint..,
I am assuming that you are requesting the profile scope in your request. If this is true then username is not a valid scope and does not form part of the list of standard claims for this scope. you should rename your claim to either nickname or preferred_username

How do I add a field for a header for an authentication token for Swagger UI?

My team has just started creating RESTful services for data that has previously been handled by a large monolithic legacy application. We want to document the api with Swagger UI and I have set up with one problem.
I need to pass a SAML token as a header parameter, otherwise when we try to click on the "Try it out!" button I get a 401 Authentication error. How do I add a field to the Swagger UI so that someone can put a String for a SAML token to be sent in the request?
This is actually really easy. I saw references to the answer in the documentation but I didn't really understand what it was saying. There is a field at the top next to where your service URL goes and you can use that field to input a string to pass as a header value. That input field has an id of #input_apiKey.
Then in the index.html file you just add a line to the addApiKeyAuthorization() javascript function telling it to take the value of that field and pass it as whatever value you need.
Example:
function addApiKeyAuthorization(){
var key = $('#input_apiKey')[0].value;
if(key && key.trim() != "") {
swaggerUi.api.clientAuthorizations.add("samlToken", new SwaggerClient.ApiKeyAuthorization("samlToken", key, "header"));
swaggerUi.api.clientAuthorizations.add("Content-Type", new SwaggerClient.ApiKeyAuthorization("Content-Type", "application/json", "header"));
swaggerUi.api.clientAuthorizations.add("Accept", new SwaggerClient.ApiKeyAuthorization("Accept", "application/json", "header"));
}
}
$('#input_apiKey').change(addApiKeyAuthorization);
This sets the Content-Type and Accept headers to the same values for every request, and takes the value in that input field at the top of the page in the green header and sets it as my SAML token. So now if I paste in a valid SAML string my request works and I get data back!

Google OAuth 2.0 redirect_uri with several parameters

How to add a parameters to the Google OAuth 2.0 redirect_uri?
Just like this:
redirect_uri=http://www.example.com/redirect.html?a=b
The b of a=b is random.
Anyone can help ?
You cannot add anything to the redirect uri, redirect uri is constant as set
in the app settings of Oauth.
eg :http://www.example.com/redirect.html
To pass several parameters to your redirect uri, have them stored in state
parameter before calling Oauth url, the url after authorization will send the same parameters to your redirect uri as
state=THE_STATE_PARAMETERS
So for your case,do this:
/1. create a json string of your parameters ->
{ "a" : "b" , "c" : 1 }
/2. do a base64UrlEncode , to make it URL safe ->
stateString = base64UrlEncode('{ "a" : "b" , "c" : 1 }');
This is a PHP example of base64UrlEncoding & decoding (http://en.wikipedia.org/wiki/Base64#URL_applications) :
function base64UrlEncode($inputStr)
{
return strtr(base64_encode($inputStr), '+/=', '-_,');
}
function base64UrlDecode($inputStr)
{
return base64_decode(strtr($inputStr, '-_,', '+/='));
}
So now state would be something like: stateString -> asawerwerwfgsg,
Pass this state in OAuth authorization URL:
https://accounts.google.com/o/oauth2/auth?
client_id=21302922996.apps.googleusercontent.com&
redirect_uri=https://www.example.com/back&
scope=https://www.google.com/m8/feeds/&
response_type=token&
state=asdafwswdwefwsdg,
For server side flow it will come along with token :
http://www.example.com/redirect.html?token=sdfwerwqerqwer&state=asdafwswdwefwsdg,
For client side flow it will come in the hash along with access token:
http://www.example.com/redirect.html#access_token=portyefghsdfgdfgsdgd&state=asdafwswdwefwsdg,
Retrieve the state, base64UrlDecode it, json_decode it, and you have your data.
See more about google OAuth 2 here:
http://code.google.com/apis/accounts/docs/OAuth2.html
Since the accepted answer does expose the actual data and misuses the state parameter instead of sticking to a nonce to protect against CSRF, I'll try to show a proper method. Rather than passing (read exposing) data it should be kept local. Hydrate it before the request and re-hydrate it after a validated request. "Validated" here means that the state-nonce of request and response match.
You need some kind of temporary client side storage. E.g. for SPA or general websites keep it in state or use the browser's localStorage, a session (or a signed cookie). For mobile apps they should use memory or any other local storage.
Before sending the request generate a nonce (see below) that will be used as state parameter for the request. Store the nonce together with the custom state (e.g. a json) in local storage.
For example, the nonce could be ih4f984hf and the custom state {"role": "customer"}. Then you could store data for re-hydration for that request like this:
"ih4f984hf": {
"role": "customer"
}
Then use only the nonce as value for the state parameter of the request. (If you absolutely want to combine the nonce and data into the state value be sure to encrypt it and be aware that the length of the value is limited!)
When receiving a response you get the value of the state parameter back. Look it up and if it matches the value in the local storage you may process the data using the stored state. If the nonces do not match the request is potentially from an attacker and should not be processed.
Generating the nonce
Remember that the nature of a nonce is that it is used once only and must be unpredictable! Unpredictable here means ideally random, but practically pseudo-random is ok if the entropry is high enough - in web apps you might want to check Web API Crypto which is supported pretty well.
For further readings this might be helpful:
http://www.thread-safe.com/2014/05/the-correct-use-of-state-parameter-in.html
https://datatracker.ietf.org/doc/html/draft-bradley-oauth-jwt-encoded-state-00
https://auth0.com/docs/protocols/state-parameters#set-and-compare-state-parameter-values
If you are in .NET you could save the parameters in the Session
HttpContext.Current.Session[{varname}]
and redirect to the authorization page without parameters
Response.Redirect(your_uri_approved_with_no_querystring_parameters);
In Javascript (Node), you could set the state property to an object of key value pairs.
const oAuth2Client = await new google.auth.OAuth2(
clientId: <clientId>,
clientSecret: <clientSecret>,
redirectUrl: <redirectUrl>,
);
return await oAuth2Client.generateAuthUrl({
access_type: "offline",
scope: <scopes>,
state: JSON.stringify({ a: "y", b: "z" }),
});
On google authorization complete, it returns of the state, code etc from ulr,
const params = JSON.parse(state); // { a: "y", b: "z" }
You can redirect parameter with url as below,
When you get response from google than you can pass parameter with url,
See below php code for same,
if (isset($_GET['code'])) {
$client->authenticate();
$_SESSION['token'] = $client->getAccessToken();
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL) . '?r=page/view');
}
In above example r=page/view is parameter on which i want the response with parameter