I am new to getstream - and I am writing some client side code
var streamclient = stream.connect('xxxxxxxx', null, '11111');
var feed = streamclient.feed('user', 'maurice', '??????') ;
How do I generate the access token for this client ?
In order to keep things secure, you'll first want to get the feed token on the server-side.
When initialising a Stream client on the server-side, you'll pass your app secret which enables access to all your app's feeds. The token can then be passed onward to your client application (single-page app, mobile app etc.).
Example server-side code:
var stream = require('getstream');
// pass the app secret when connecting on the server-side
streamclient = stream.connect('<key>', '<secret>', '<app id>');
// no feed token is req'd when the Stream client was connected with an app secret
var feed = streamclient.feed('user', 'maurice');
var feedToken = feed.token // or feed.getReadOnlyToken();
The client-side snippet you posted looks fine for initialising the feed variable.
Related
I am new to JWT, not new to react, but am very confused on how to decode a JWT from the front end. I initially thought that I can store the JWT Secret in the .env file but many sources say that it is a very bad idea to do so. I have the backend setup to send me a JWT when you login. But without storing the secret key in the front end as well, how would I decode the information?
Backend:
if(bcrypt.compareSync(ctx.params.password, hashed_db_password)) {
ctx.status = 200;
const payload = { data: tuples[0] };
const options = { expiresIn: '1h', issuer: 'testIssuer'};
const secret = process.env.JWT_SECRET;
const token = jwt.sign(payload, secret, options);
ctx.body = token;
return resolve();
}
How I thought front end should have been:
let data = JWT.verify(result.data, process.env.REACT_APP_JWT_SECRET, options);
I have also read alot that the backend should do validation but then wouldnt that just be a huge security risk to validate, then send back unsecure raw user information? Any information would be greatly appreciated.
BTW, I am using Reactjs, Node.js, Express, and MySql
You should not store JWT secret in client side.
To decode token, you don't need the JWT secret.
You can decode the token using jwt-decode package.
Or if you want to decode without using a package, you can look at here.
You can store it in your main components state, Redux store, React Context, localstorage and so on..
You should get the JWT only when your authentication is successful and you should send it with each request to the server, you don't need to decode it on the front-end you just pass the encoded value to the server and decode it somewhere on the backend (some kind of middle-ware)
I'm building API with Nodejs using firebase-funtions for login with email and password function. But when I use firebase.auth() then recieve error: firebase.auth() is not a function. I searched a long time but don't have result as expect. I have any questions:
1/ Can we use firebase.auth() (it's client-SDK) on firebase-functions ?
2/ If can't use it. What we should do authenticate email/password from firebase as RESTful API.
Here's my code:
const firebase = require('firebase');
const functions = require('firebase-functions');
const admin = require('firebase-admin');
var serviceAccount = require("./serviceAccountKey.json");
var firebaseConfig = {
// my config
};
firebase.initializeApp(firebaseConfig);
admin.initializeApp({
// my config
});
As I implied in my first comment, you can't sign in a user on the server side of your app. It's not clear to me why you need to do that. Each supported mobile and web platform has their own way of signing in the user locally. They should not be sharing some server code to do that particular task. There are other things you could delegate to a server, but signing in is not one of them.
The client needs to sign in on its own because it needs to generate a ID token that identifies the user, so that the client can make requests to other Firebase products that will be authorized for that particular user. This token must come from the client in order to be secure.
From what i understand the purpose of the Authorization Code flow is to exchange the auth code for access token. This exchange happens between the server which serves the page and authorization server so that the actual access token is not exposed to the client user.
How should the page server store the access token once it is obtained? I was learning from a Pluralsight example in which there is this part of code:
public static HttpClient GetClient()
{
HttpClient client = new HttpClient();
var accessToken = RequestAccessTokenAuthorizationCode();
client.SetBearerToken(accessToken);
client.BaseAddress = new Uri(IdentityConstants.API);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
return client;
}
private static string RequestAccessTokenAuthorizationCode()
{
// did we store the token before?
var cookie = HttpContext.Current.Request.Cookies.Get("ClientMVCCookie.AuthCode");
if (cookie != null && cookie["access_token"] != null && !string.IsNullOrEmpty(cookie["access_token"]))
{
return cookie["access_token"];
}
// no token found - request one
// we'll pass through the URI we want to return to as state
var state = HttpContext.Current.Request.Url.OriginalString;
var authorizeRequest = new IdentityModel.Client.AuthorizeRequest(
IdentityConstants.AuthEndoint);
var url = authorizeRequest.CreateAuthorizeUrl(IdentityConstants.MVCClientSecret, "code", "management secret",
IdentityConstants.MVCAuthCodeCallback, state);
HttpContext.Current.Response.Redirect(url);
return null;
}
}
This will cause each request to check if there is an access token stored in the cookie. If not then the flow will be initiated. The callback looks like this:
public class CallbackController : Controller
{
// GET: STSCallback
public async Task<ActionResult> Index()
{
// get the authorization code from the query string
var authCode = Request.QueryString["code"];
// with the auth code, we can request an access token.
var client = new TokenClient(
IdentityConstants.TokenEndoint,
"mvc_client_auth_code",
IdentityConstants.MVCClientSecretAuthCode);
var tokenResponse = await client.RequestAuthorizationCodeAsync(
authCode,
IdentityConstants.MVCAuthCodeCallback);
// we save the token in a cookie for use later on
var cookie = Response.Cookies["ClientMVCCookie.AuthCode"];
cookie.Expires = DateTime.Now.AddMinutes(1);
cookie["access_token"] = tokenResponse.AccessToken;
// get the state (uri to return to)
var state = Request.QueryString["state"];
// redirect to the URI saved in state
return Redirect(state);
}
}
Doesn't storing the access token in the cookie defeath the whole purpose of the authorization code flow? The cookie will be transmitted to the client browser thus exposing it to the client? Am i missing something? It this is not the correct way to store the token, how should it be stored?
The client, in OAuth terminology, is the component that makes requests to the resource server, in your case, the client is the server of a web application (NOT the browser).
Therefore, the access token should be stored on the web application server only. It should not be exposed to the browser, and it doesn't need to, because the browser never makes any direct requests to the resource server. It talks to the web application server instead, which in turn makes requests to the resource server using the access token.
How the browser authenticates itself with the web application server has nothing to do with OAuth 2.0. For example, it might be a regular session cookie, and the web application server might associate each session or each user with an access token.
The token request, which exchanges the authentication code for an access token, is done by the web application server, and the web application server should authenticate itself with the authorization server (e.g., using a shared client_secret).
Authorization code flow ensures that the client can be authenticated, which protects against malicious clients posing as legitimate clients. Not all web application clients have a server component, and in some cases, requests to the resource server are made directly by JavaScript code in the browser. In such situations, the browser is the client, and the access token must be stored by the browser (in a JavaScript variable, local storage or a cookie). In this case, the client cannot be authenticated (but a reasonable amount of security may be achieved by using TLS and the server redirecting only to registered endpoint URLs).
Recommended reading regarding OAuth 2.0 security: https://www.rfc-editor.org/rfc/rfc6819#section-4.3.3 (RFC 6819)
The cookie is never exposed to the browser. It is part of the response returned from the authorization server to the client, which itself is a server, not a browser. The CallbackController, which implements the redirection endpoint, extracts the cookie from the response.
The cookie is never passed on to the browser. How the browser authenticates itself with the client's application server is not shown in your sample code, and it is not part of OAuth.
The authorization server could store the token in the request body (e.g., in JSON format) rather than in a cookie. However, this makes no difference, because the client can see and process the entire response anyway.
For details, see my other answer: https://stackoverflow.com/a/44655679/2279059
Side note: The CallbackController uses state to store a final URL to redirect the browser to. This is non-standard but works. However, state is actually meant to protect the redirection endpoints against CSRF attacks. The CallbackController does not validate state but blindly redirects to whatever URL was given. Probably this detail was left out, because the code was meant as an example. However, it shows that this code is probably not entirely production-ready.
If you are going to request a rest resource from the browser, the flow you need is Implicit Grant. Check this Auth0 post to decide between the flows https://auth0.com/docs/api-auth/which-oauth-flow-to-use. If you want to use the access token from server you should store the Authorization code and generate an access token every time you need it, access token is not intended to live more than 5 minutes, you don't need to store it
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Recently I have been reading up on OAuth2, OpenID Connect etc. But still very lost at what to use when and how to implement it. I am thinking of using NodeJS for now.
Lets say I want to create a blog service. This service will expose API's for clients to use. "Clients" include an admin CMS. I am thinking it will be nice to decouple my server and client (UI). I can change the UI without touching the server. These clients are likely going to be single page web applications.
Ok 1st question: In this example, should I be using OAuth2? Why? Isit just because I am authorizing the admin app to access by blog?
Since its SPA's, I think the right strategy is OAuth2 Implicit Flow?
For each app, eg. admin cms, I will have to generate an AppID which is passed to the auth server. No app secret is required correct?
Isit possible to use google login in this case (instead of username/password)? Does OpenID connect do this?
How do I implement all these in NodeJS? I see https://github.com/jaredhanson/oauth2orize, but I do not see how to implement the implicit flow.
I do see an unofficial example https://github.com/reneweb/oauth2orize_implicit_example/blob/master/app.js, but what I am thinking is why is sessions required? I thought one of the goals of tokens is so that server can be stateless?
I am also wondering, when should I use API key/secret authentication?
Let's examine your questions
Should I be using OAuth2? Why?
A: Well, as today the old OpenId 2 authentication protocol has been marked as obsolete (November 2014) and OpenId Connect is an identity layer built on top of OAuth2 so the real question is if is important for you and your business to know and verify the identity of your users (the authentication part). If the answer is "yes" then go for OpenId Connect otherwise you can choose any of the two, the one you feel more comfortable with.
Since its SPA's, I think the right strategy is OAuth2 Implicit Flow?
A: Not really. You can implement any strategy when using a SPA, some takes more work than others and greatly depends on what are you trying to accomplish. The implicit flow is the simplest but it does not authenticate your users since an access token is issued directly.
When issuing an access token during the implicit grant flow, the authorization server does not authenticate the client. In some cases, the client identity can be verified via the redirection URI used to deliver the access token to the client.
I would not recommend this flow for your app (or any app that needs a decent level of security1).
If you want to keep it simple you should use Resource Owner Grant flow with an username and password but again there is nothing that prevents you of implementing the Authorization Code Grant flow especially if you want to allow third parties apps to use your service (which in my opinion is a winning strategy) and it will be relatively more secure than the others since it requires explicit consent from the user.
For each app, eg. admin cms, I will have to generate an AppID which is passed to the auth server. No app secret is required correct?
A: Yes that is correct but the client_secret can be used to add an extra layer of security to the token endpoint in the resource owner flow when you can't use Basic authentication, this is not required in any other flow.2 3
The authorization server MUST:
require client authentication for confidential clients or for any
client that was issued client credentials (or with other
authentication requirements),
authenticate the client if client authentication is included, and
validate the resource owner password credentials using its
existing password validation algorithm.
and
Alternatively, the authorization server MAY support including the client credentials in the request-body (...) Including the client credentials in the request-body using the two parameters is NOT RECOMMENDED and SHOULD be limited to clients unable to directly utilize the HTTP Basic authentication scheme (or other password-based HTTP authentication schemes)
Is it possible to use google login in this case (instead of username/password)? Does OpenID connect do this?
A: Yes, is possible to use google login in which case you are just delegating the authentication and authorization job to the google servers. One of the benefits of working with an authorization server is the ability to have a single login to access other resources without having to create a local account for each of the resources you want to access.
How do I implement all these in NodeJS?
Well you started with the right foot. Using oaut2horize is the most simple way to implement an authorization server to issue tokens. All other libraries I tested were too complicated of use and integrate with node and express (disclaimer: this is just my opinion). OAuthorize plays nicely with passport.js(both from the same author) which is a great framework to enforce the authentication and authorization with over 300+ strategies like google, facebook, github, etc. You can easily integrate google using passport-google(obsolete), passport-google-oauth and passport-google-plus.
Let's go for the example
storage.js
// An array to store our clients. You should likely store this in a
// in-memory storage mechanism like Redis
// you should generate one of this for any of your api consumers
var clients = [
{id: 'as34sHWs34'}
// can include additional info like:
// client_secret or password
// redirect uri from which client calls are expected to originate
];
// An array to store our tokens. Like the clients this should go in a memory storage
var tokens = [];
// Authorization codes storage. Those will be exchanged for tokens at the end of the flow.
// Should be persisted in memory as well for fast access.
var codes = [];
module.exports = {
clients: clients,
tokens: tokens,
codes: codes
};
oauth.js
// Sample implementation of Authorization Code Grant
var oauth2orize = require('oauth2orize');
var _ = require('lodash');
var storage = require('./storage');
// Create an authorization server
var server = oauth2orize.createServer();
// multiple http request responses will be used in the authorization process
// so we need to store the client_id in the session
// to later restore it from storage using only the id
server.serializeClient(function (client, done) {
// return no error so the flow can continue and pass the client_id.
return done(null, client.id);
});
// here we restore from storage the client serialized in the session
// to continue negotiation
server.deserializeClient(function (id, done) {
// return no error and pass a full client from the serialized client_id
return done(null, _.find(clients, {id: id}));
});
// this is the logic that will handle step A of oauth 2 flow
// this function will be invoked when the client try to access the authorization endpoint
server.grant(oauth2orize.grant.code(function (client, redirectURI, user, ares, done) {
// you should generate this code any way you want but following the spec
// https://www.rfc-editor.org/rfc/rfc6749#appendix-A.11
var generatedGrantCode = uid(16);
// this is the data we store in memory to use in comparisons later in the flow
var authCode = {code: generatedGrantCode, client_id: client.id, uri: redirectURI, user_id: user.id};
// store the code in memory for later retrieval
codes.push(authCode);
// and invoke the callback with the code to send it to the client
// this is where step B of the oauth2 flow takes place.
// to deny access invoke an error with done(error);
// to grant access invoke with done(null, code);
done(null, generatedGrantCode);
}));
// Step C is initiated by the user-agent(eg. the browser)
// This is step D and E of the oauth2 flow
// where we exchange a code for a token
server.exchange(oauth2orize.exchange.code(function (client, code, redirectURI, done) {
var authCode = _.find(codes, {code: code});
// if the code presented is not found return an error or false to deny access
if (!authCode) {
return done(false);
}
// if the client_id from the current request is not the same that the previous to obtain the code
// return false to deny access
if (client.id !== authCode.client_id) {
return done(null, false);
}
// if the uris from step C and E are not the same deny access
if (redirectURI !== authCode.uri) {
return done(null, false);
}
// generate a new token
var generatedTokenCode = uid(256);
var token = {token: generatedTokenCode, user_id: authCode.user_id, client_id: authCode.client_id};
tokens.push(token);
// end the flow in the server by returning a token to the client
done(null, token);
}));
// Sample utility function to generate tokens and grant codes.
// Taken from oauth2orize samples
function uid(len) {
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var buf = []
, chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
, charlen = chars.length;
for (var i = 0; i < len; ++i) {
buf.push(chars[getRandomInt(0, charlen - 1)]);
}
return buf.join('');
}
module.exports = server;
app.js
var express = require('express');
var passport = require('passport');
var AuthorizationError = require('oauth2orize').AuthorizationError;
var login = require('connect-ensure-login');
var storage = require('./storage');
var _ = require('lodash');
app = express();
var server = require('./oauthserver');
// ... all the standard express configuration
app.use(express.session({ secret: 'secret code' }));
app.use(passport.initialize());
app.use(passport.session());
app.get('/oauth/authorize',
login.ensureLoggedIn(),
server.authorization(function(clientID, redirectURI, done) {
var client = _.find(storage.clients, {id: clientID});
if (client) {
return done(null, client, redirectURI);
} else {
return done(new AuthorizationError('Access denied'));
}
}),
function(req, res){
res.render('dialog', { transactionID: req.oauth2.transactionID, user: req.user, client: req.oauth2.client });
});
app.post('/oauth/authorize/decision',
login.ensureLoggedIn(),
server.decision()
);
app.post('/oauth/token',
passport.authenticate(['basic', 'oauth2-client-password'], { session: false }),
server.token(),
server.errorHandler()
);
(...) but what I am thinking is why is sessions required? I thought one of the goals of tokens is so that server can be stateless?
When a client redirects a user to user authorization endpoint, an authorization transaction is initiated. To complete the transaction, the user must authenticate and approve the authorization request. Because this may involve multiple HTTP request/response exchanges, the transaction is stored in the session.
Well yes, but the session is used for the token negotiation process. Later you enforce authorization sending the token in an Authorization header to authorize each request using the obtained token.
In my experience, OAuth2 is the standard way of securing APIs. I'd recommend using OpenID Connect though as it adds authentication to OAuth2's otherwise authorization-based spec. You can also get Single-Sign-On between your "clients".
Since its SPA's, I think the right strategy is OAuth2 Implicit Flow?
De-coupling your clients and servers is a nice concept (and I'd generally do the same too) however, I'd recommend the authorization code flow instead as it doesn't expose the token to the browser. Read http://alexbilbie.com/2014/11/oauth-and-javascript/. Use a thin server-side proxy instead to add the tokens to the request. Still, I generally avoid using any server-generated code on the client (like JSPs in java or erb/haml in rails) since it couples the client to the server too much.
For each app, eg. admin cms, I will have to generate an AppID which is passed to the auth server. No app secret is required correct?
You'll need a client ID for implicit flow. If you use authorization code flow (recommended), you'll need both an ID and secret but the secret will be kept in the thin server-side proxy rather than a client-side only app (since it can't be secret in that case)
Is it possible to use google login in this case (instead of username/password)? Does OpenID connect do this?
Yes. Google uses openid connect
How do I implement all these in NodeJS? I see https://github.com/jaredhanson/oauth2orize, but I do not see how to implement the implicit flow.
A nice thing about openid connect is that (if you use another provider like google), you don't have to implement the provider yourself and you'll only need to write client code (and/or utilize client libaries). See http://openid.net/developers/libraries/ for different certified implementations. See https://www.npmjs.com/package/passport-openidconnect for nodejs.
Lets say I have a web client (i.e. MVC 4 client) that authenticates users using an oAuth provider (i.e. Facebook, Google etc).
I want to call another web service in my client logic, and that web service also authenticates with oAuth providers.
What would the web service request look like from the client? What do I need to pass to the web service?
I suggest you review this question, How do I authorize access to ServiceStack resources using OAuth2 access tokens via DotNetOpenAuth?. The poster provided his final solution, including a link to a sample solution, which he has graciously open sourced. The client side code, for his solution, looks like this:
// Create the ServiceStack API client and the request DTO
var apiClient = new JsonServiceClient("http://api.mysite.com/");
var apiRequestDto = new Shortlists { Name = "dylan" };
// Wire up the ServiceStack client filter so that DotNetOpenAuth can
// add the authorization header before the request is sent
// to the API server
apiClient.LocalHttpWebRequestFilter = request => {
// This is the magic line that makes all the client-side magic work :)
ClientBase.AuthorizeRequest(request, accessTokenTextBox.Text);
}
// Send the API request and dump the response to our output TextBox
var helloResponseDto = apiClient.Get(apiRequestDto);
Console.WriteLine(helloResponseDto.Result);
A similar solution is provided here: https://stackoverflow.com/a/13791078/149060 which demonstrates request signing as per OAuth 1.0a
var client = new JsonServiceClient (baseUri);
client.LocalHttpWebRequestFilter += (request) => {
// compute signature using request and a previously obtained
// access token
string authorization_header = CalculateSignature (request, access_token);
request.Headers.Add ("Authorization", authorization_header);
};
var response = client.Get<MySecuredResponse> ("/my/service");
You will, of course, need to adjust to fit the requirements of your OAuth providers, i.e. signing, token, etc.