Giter Site home page Giter Site logo

lynndylanhurley / redux-auth Goto Github PK

View Code? Open in Web Editor NEW
2.1K 47.0 264.0 4.72 MB

Complete token authentication system for react + redux that supports isomorphic rendering.

License: Do What The F*ck You Want To Public License

JavaScript 99.89% CSS 0.11%

redux-auth's Introduction

redux auth

Simple, secure authentication for react + redux

npm version Build Status Coverage Status

TL;DR - View the Live Demo

You can see a complete working example here. The code for the demo is here.

Click this button to deploy the demo app to your own server:

Deploy

--

Features:

This project comes bundled with a test app. You can run the demo locally by following these instructions, or you can use it here in production.

The demo uses React, and the source can be found here.

--

Table of Contents

About this plugin

This plugin relies on token based authentication. This requires coordination between the client and the server. Diagrams are included to illustrate this relationship.

This plugin was designed to work out of the box with the wonderful devise token auth gem, but it's flexible enough to be used in just about any environment.

About security: read here for more information on securing your token auth system. The devise token auth gem has adequate security measures in place, and this plugin was built to work seamlessly with that gem.

--

Installation

Only npm is currently supported.

npm install redux-auth --save

If you want to use the Material UI or Bootstrap themes, you will need to install those libraries as well.

# install material ui
npm install material-ui --save

# or bootstrap
npm install react-bootstrap --save

Material UI uses inline styles so no further configuration is needed. But with the bootstrap theme, the CSS will also need to be included. Read more at the React Bootstrap project page.

You must also install and use a json loader

--

Usage

Components

There are 3 Themes included in this module.

  1. Material UI
  2. Bootstrap
  3. A default theme

The default theme has no styling, and honestly it just looks really bad. But if you hate heavy UI frameworks and you like to style everything yourself, then you will love the default theme.

All components can make their own API requests, display errors, and display success messages out of the box.

The examples shown below use the Material UI theme.

--

EmailSignUpForm

A form used for email based registration.

Material UI email sign up

EmailSignUpForm props:
  • endpoint: The key of the target provider service as represented in the endpoint configuration block.
  • inputProps: An object containing the following attributes:
    • email: An object that will override the email input component's default props.
    • password: An object that will override the password input component's default props.
    • passwordConfirmation: An object that will override the password confirmation input component's default props.
    • submit: An object that will override the submit button component's default props.
EmailSignUpForm usage
// default theme
import { EmailSignUpForm } from "redux-auth/default-theme";

// material ui theme
import { EmailSignUpForm } from "redux-auth/material-ui-theme";

// bootstrap theme
import { EmailSignUpForm } from "redux-auth/bootstrap-theme";

// render
render: () {
  return <EmailSignUpForm />;
}

View EmailSignUpForm API Expectations

--

EmailSignInForm

A form used to sign in using accounts that were registered by email.

Material UI email sign in

EmailSignInForm props:
  • endpoint: The key of the target provider service as represented in the endpoint configuration block.
  • next: A method to call on successful sign-in.
  • inputProps: An object containing the following attributes:
    • email: An object that will override the email input component's default props.
    • password: An object that will override the password input component's default props.
    • submit: An object that will override the submit button component's default props.
// default theme
import { EmailSignInForm } from "redux-auth/default-theme";

// material ui theme
import { EmailSignInForm } from "redux-auth/material-ui-theme";

// bootstrap theme
import { EmailSignInForm } from "redux-auth/bootstrap-theme";

// render
render: () {
  return <EmailSignInForm />;
}

View EmailSignInForm API expectations

--

OAuthSignInButton

A button used to authenticate using an OAuth provider (facebook, github, etc.).

Material UI OAuth sign in

OAuthSignInButton props:
  • endpoint: The key of the target provider service as represented in the endpoint configuration block.
  • provider: The name of the target provider service as represented in the authProviderPaths endpoint configuration.
  • next: A method to call on successful sign-in.

Any additional properties will be passed on the button component of the given theme.

// default theme
import { OAuthSignInButton } from "redux-auth/default-theme";

// material ui theme
import { OAuthSignInButton } from "redux-auth/material-ui-theme";

// bootstrap theme
import { OAuthSignInButton } from "redux-auth/bootstrap-theme";

// render
render: () {
  // using the default label
  return <OAuthSignInButton />;

  // or using custom label text
  return <OAuthSignInButton>Custom Label</OAuthSignInButton>;
}

View OAuthSignInButton API expectations

--

SignOutButton

A button used to end the current user's session.

Material UI sign out

SignOutButton props:
  • endpoint: The key of the target provider service as represented in the endpoint configuration block. If this property isn't provided, the current signed in user will be signed out regardless of their user type.
  • next: A method to call upon successful sign-out.

Any additional properties will be passed on the button component of the given theme.

// default theme
import { SignOutButton } from "redux-auth/default-theme";

// material ui theme
import { SignOutButton } from "redux-auth/material-ui-theme";

// bootstrap theme
import { SignOutButton } from "redux-auth/bootstrap-theme";

// render
render: () {
  // using the default label
  return <SignOutButton />;

  // or using custom label text
  return <SignOutButton>Custom Label</SignOutButton>;
}

View SignOutButton API expectations

--

DestroyAccountButton

A button used to destroy the account of the current user. This will also end the destroyed user's session.

Material UI destroy account

DestroyAccountButton props:
  • endpoint: The key of the target provider service as represented in the endpoint configuration block. If this property isn't provided, the current signed in user's account will be destroyed regardless of their user type.

Any additional properties will be passed on the button component of the given theme.

// default theme
import { DestroyAccountButton } from "redux-auth/default-theme";

// material ui theme
import { DestroyAccountButton } from "redux-auth/material-ui-theme";

// bootstrap theme
import { DestroyAccountButton } from "redux-auth/bootstrap-theme";

// render
render: () {
  // using the default label
  return <DestroyAccountButton />;

  // or using custom label text
  return <DestroyAccountButton>Custom Label</DestroyAccountButton>;
}

View DestroyAccountButton API Expectations

--

RequestPasswordResetForm

A form used to send password reset emails to users that forgot their password. When users click the link included in the email, they will be redirected to the site that the request was made from. A modal will appear that contains a form allowing the user to create a new password.

Material UI request password reset

RequestPasswordResetForm props:
  • endpoint: The key of the target provider service as represented in the endpoint configuration block.
  • inputProps: An object containing the following attributes:
    • email: An object that will override the email input component's default props.
    • submit: An object that will override the submit button component's default props.
// default theme
import { RequestPasswordResetForm } from "redux-auth/default-theme";

// material ui theme
import { RequestPasswordResetForm } from "redux-auth/material-ui-theme";

// bootstrap theme
import { RequestPasswordResetForm } from "redux-auth/bootstrap-theme";

// render
render: () {
  return <RequestPassswordResetForm />;
}

View RequestPasswordResetForm API Expectations

--

UpdatePasswordForm

A form that can be used to change the current user's password.

Material UI update password

UpdatePasswordForm props:
  • endpoint: The key of the target provider service as represented in the endpoint configuration block. If this value is not provided, the current user's password will be updated regardless of their user type.
  • inputProps: An object containing the following attributes:
    • password: An object that will override the password input component's default props.
    • passwordConfirmation: An object that will override the password confirmation input component's default props.
    • submit: An object that will override the submit button component's default props.
// default theme
import { UpdatePasswordForm } from "redux-auth/default-theme";

// material ui theme
import { UpdatePasswordForm } from "redux-auth/material-ui-theme";

// bootstrap theme
import { UpdatePasswordForm } from "redux-auth/bootstrap-theme";

// render
render: () {
  return <UpdatePasswordForm />;
}

View UpdatePasswordForm API Expectations

--

AuthGlobals

This component contains all of the modals used in authentication, and also the component that is used to pass credentials from the server to the client when using server side rendering.

This component MUST live at the top level of your application outside of your routes.

AuthGlobals example using redux-router

The following example shows the relevant router configuration. Note that this is not a complete example. See the demo app for a complete, working setup.

// default theme
import { AuthGlobals } from "redux-auth/default-theme";

// material ui theme
import { AuthGlobals } from "redux-auth/material-ui-theme";

// bootstrap theme
import { AuthGlobals } from "redux-auth/bootstrap-theme";

// your main app component. notice that AuthGlobals lives at the same level
// as the app's children.
class App extends React.Component {
  render() {
    return (
      <div>
        <AuthGlobals />
        {this.props.children}
      </div>
    );
  }
}

// example routes. the nested routes here will replace "this.props.children"
// in the example above
var routes = (
  <Route path="/" component={App}>
    <IndexRoute component={Main} />
    <Route path="alt" component={Alt} />
    <Route path="login" component={SignIn} />
    <Route path="account" component={Account} onEnter={requireAuth} />
  </Route>
);

--

Methods

configure

This must be run before your app is initialized. This should be run on both the server, and on the client. The server will need an additional argument containing information about the current request's cookies and location.

configure arguments
  • endpoints: An object containing information about your API. This at least needs to contain the full path to your URL as the apiUrl property. See here for a complete list of endpoint config options.
  • settings: When rendering serverside, this will need to be an object that contains the following attributes:
    • isServer: A boolean that must be set to true when rendering server-side.
    • cookies: A string representation of the cookies from the current request. This will be parsed for any auth credentials.
    • location: A string representation of the current request's URL.

Additionaly when rendering on client side some additional settings can be passed in settings object.

  • cleanSession: A boolean that tells if all locally stored credentials will be flushed.
  • clientOnly: A boolean that tells if code is run only on client side. Should be set true with only client-side usage.

--

configure example
import { configure } from "redux-auth";

// server-side usage
store.dispatch(configure(
  {apiUrl: "https://api.graveflex.com"},
  {isServer: true, cookies, currentLocation}
)).then(({redirectPath, blank} = {}) => {
  // if `blank` is true, this is an OAuth redirect and should not
  // be rendered

  // use your server to render your app, or redirect
  // to another location if the user is unauthorized.

  // see the demo app for a more complete example.
});

// client-side usage
store.dispatch(configure(
  {apiUrl: "https://api.graveflex.com"},
  {serverSideRendering: true, cleanSession: true}
)).then(() => {
  // your store should now have the current user. now render your
  // app to the DOM. see the demo app for a more complete example.
});

--

fetch

A wrapper around the whatwg fetch implementation that automatically sends and tracks authentication headers. See here for the complete spec.

Any requests to the API that rely on authentication will need to use the fetch function included in this library.

--

fetch example
import { fetch } from "redux-auth";

// usage
fetch("http://api.mysite.com").then(resp => {
  alert(`Api response: `${resp}`);
});

--

Configuration

This is the most difficult step, but only because configuring a redux app is inherently difficult.

The following example assumes that you are familiar with redux, and that you know how to create a store. Also keep in mind that this is a really basic example that does not even include routing. See the demo app for a more complete example.

This example assumes a directory structure that looks like this:

src/
  app.js
  client.js
  server.js
config shared by both client and server
// app.js
import React from "react";
import {Provider} from "react-redux";
import {configure, authStateReducer} from "redux-auth";
import {createStore, compose, applyMiddleware, combineReducers} from "redux";
import {AuthGlobals} from "redux-auth/default-theme";

class App extends React.Component {
  render() {
    return (
      <div>
        <AuthGlobals />
        {this.props.children}
      </div>
    );
  }
}

// create your main reducer
const reducer = combineReducers({
  auth: authStateReducer,
  // ... add your own reducers here
});

// create your app's store.
// note that thunk is required to use redux-auth
const store = compose(
  applyMiddleware(thunk),
  // ... add additional middleware here (router, etc.)
)(createStore)(reducer);

// a single function can be used for both client and server-side rendering.
// when run from the server, this function will need to know the cookies and
// url of the current request. also be sure to set `isServer` to true.
export function renderApp({cookies, isServer, currentLocation} = {}) {
  // configure redux-auth BEFORE rendering the page
  store.dispatch(configure(
    // use the FULL PATH to your API
    {apiUrl: "http://api.catfancy.com"},
    {isServer, cookies, currentLocation}
  )).then(({redirectPath, blank} = {}) => {
    if (blank) {
      // if `blank` is true, this is an OAuth redirect and should not
      // be rendered
      return <noscript />;
    } else {
      return (
        <Provider store={store} key="provider">
          <App />
        </Provider>
      );
    }
  });
}
server-side rendering configuration
// server.js
import qs from "query-string";
import {renderToString} from "react-dom/server";
import { renderApp } from "./app";

// render the main app component into an html page
function getMarkup(appComponent) {
  var markup = renderToString(appComponent)

  return `<!doctype html>
    <html>
      <head>
        <title>Redux Auth – Isomorphic Example</title>
      </head>
    <body>
      <div id="react-root">${markup}</div>
      <script src="/path/to/my/scripts.js"></script>
    </body>
  </html>`;
}

// this function will differ depending on the serverside framework that
// you decide to use (express, hapi, etc.). The following example uses hapi
server.ext("onPreResponse", (request, reply) => {
  var query = qs.stringify(request.query);
  var currentLocation = request.path + (query.length ? "?" + query : "");
  var cookies = request.headers.cookies;

  renderApp({
    isServer: true,
    cookies,
    currentLocation
  }).then(appComponent => {
    reply(getMarkup(appComponent));
  });
}
client side rendering configuration
// client.js
import React from "react";
import ReactDOM from "react-dom";
import { renderApp } from "./app";

const reactRoot = window.document.getElementById("react-root");
renderApp().then(appComponent => {
  ReactDOM.render(appComponent, reactRoot);
});

Note: be sure to include the AuthGlobals component at the top level of your application. This means outside of your Routes if you're using something like react-router.

See below for the complete list of configuration options.

Multiple user types

This plugin allows for the use of multiple user authentication endpoint configurations. The following example assumes that the API supports two user classes, User and EvilUser. The following examples assume that User authentication routes are mounted at /auth, and the EvilUser authentication routes are mounted at evil_user_auth.

Multiple user type configuration

When using a single user type, you will pass a single object to the configure method as shown in the following example.

store.dispatch(configure({
  apiUrl: 'https://devise-token-auth.dev'
}));

When using multiple user types, you will instead pass an array of configurations, as shown in the following example.

store.dispatch(configure([
  {
    default: {
      apiUrl: 'https://devise-token-auth.dev'
    }
  }, {
    evilUser: {
      apiUrl:                  'https://devise-token-auth.dev',
      signOutUrl:              '/evil_user_auth/sign_out',
      emailSignInPath:         '/evil_user_auth/sign_in',
      emailRegistrationPath:   '/evil_user_auth',
      accountUpdatePath:       '/evil_user_auth',
      accountDeletePath:       '/evil_user_auth',
      passwordResetPath:       '/evil_user_auth/password',
      passwordUpdatePath:      '/evil_user_auth/password',
      tokenValidationPath:     '/evil_user_auth/validate_token',
      authProviderPaths: {
        github:    '/evil_user_auth/github',
        facebook:  '/evil_user_auth/facebook',
        google:    '/evil_user_auth/google_oauth2'
      }
    }
  }
], {
  isServer,
  cookies,
  currentLocation
));

Using multiple endpoints with redux-auth components

All components accept an endpoint attribute that will determine which of the endpoint configurations the component should use. For forms that are used by non-authenticated users users (EmailSignInForm, OAuthSignInButton, etc.), the first configuration in the endpoint config will be used as the default if this value is not provided. For forms used by authenticated users (SignOutButton, UpdatePassword, etc.), the current user's endpoint will be used by default if this value is not provided.

The following example assumes a configuration where two endpoints have been defined, default and auth:

Component example:
import { EmailSignInForm } from "redux-auth/default-theme";

// within render method
<EmailSignInForm endpoint="alt" />

--

Endpoint config options

This is the complete list of options that can be passed to the endpoint config.

import { configure } from "redux-auth";

// ... configure store, routes, etc... //

store.dispatch(configure({
  apiUrl:                  'https://devise-token-auth.dev',
  signOutPath:             '/evil_user_auth/sign_out',
  emailSignInPath:         '/evil_user_auth/sign_in',
  emailRegistrationPath:   '/evil_user_auth',
  accountUpdatePath:       '/evil_user_auth',
  accountDeletePath:       '/evil_user_auth',
  passwordResetPath:       '/evil_user_auth/password',
  passwordUpdatePath:      '/evil_user_auth/password',
  tokenValidationPath:     '/evil_user_auth/validate_token',
  authProviderPaths: {
    github:    '/evil_user_auth/github',
    facebook:  '/evil_user_auth/facebook',
    google:    '/evil_user_auth/google_oauth2'
  }
}).then(// ... render your app ... //

apiUrl

string

The base route to your api. Each of the following paths will be relative to this URL. Authentication headers will only be added to requests with this value as the base URL.

--

tokenValidationPath

string

Path (relative to apiUrl) to validate authentication tokens. Read more.

--

signOutPath

string

Path (relative to apiUrl) to de-authenticate the current user. This will destroy the user's token both server-side and client-side.

--

authProviderPaths

object

An object containing paths to auth endpoints. Keys should be the names of the providers, and the values should be the auth paths relative to the apiUrl. Read more.

--

emailRegistrationPath

string

Path (relative to apiUrl) for submitting new email registrations. Read more.

--

accountUpdatePath

string

Path (relative to apiUrl) for submitting account update requests.

--

accountDeletePath

string

Path (relative to apiUrl) for submitting account deletion requests.

--

emailSignInPath

string

Path (relative to apiUrl) for signing in to an existing email account.

--

passwordResetPath

string

Path (relative to apiUrl) for requesting password reset emails.

--

passwordUpdatePath

string

Path (relative to apiUrl) for submitting new passwords for authenticated users.

--

Extended Documentation

Follow these links to learn more about what the API expects from this library, and to see diagrams on how it all fits together. All of this stuff happens automatically when using this library with the devise token auth gem, but this information will be useful if you need to implement your own API.

Contributing

  1. Create a feature branch with your changes.
  2. Write some test cases.
  3. Make all the tests pass.
  4. Issue a pull request.

I will grant you commit access if you send quality pull requests.

Development

Running the dev server

There is a test project in the demo directory of this app. To start a dev server, perform the following steps.

  1. cd to the root of this project.
  2. cd dummy
  3. npm install
  4. npm run watch

A hot-reloading dev server will start on localhost:8000. The test suite will be run as well.

Running the tests

If you just want to run the tests, follow these steps:

  1. cd into the root of this project
  2. npm install
  3. npm test

Testing against a live API

This plugin was built against this API. You can use this, or feel free to use your own.

Credits

Thanks to the following contributors:

Code and ideas were stolen from the following sources:

License

WTFPL © Lynn Dylan Hurley

redux-auth's People

Contributors

baopham avatar clark-teeple avatar hhhonzik avatar istoramandiri avatar ivawzh avatar jlonardi avatar jonathonwalz avatar lynndylanhurley avatar mabana avatar nathanmalishev avatar rickwong avatar supasate avatar themouette avatar yannickschuchmann avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

redux-auth's Issues

Use with Passport

This is an awesome idea, congrats!
Can the Passport library be used? Are there any plans on supporting it.

Client-only (non-universal) support

First, thank you for this wonderful library. It's been a joy to start playing with it and have such great documentation to work from.

I'm wondering how doable it would be currently to use it in a non-universal app. I assume it's conceptually possible since that appears to be how ng-token-auth works, but I'm curious to hear what you think it'd take to support that, if you think it'd be worthwhile to support that usage. I may be volunteering a future pull request if you're interested in this and think it wouldn't be too daunting.

configure() should not automatically try to authenticate on backend

It's not flexible enough. Instead it should (imo) only try to authenticate when developer/component requests it. This way configure() only set endpoint url and then redux-auth itself saves user (in any login action) to localStorage with token + token_expire_time.
Right now, redux-auth spams unnecessary authentification event on every page load, not to say it's not even working at this moment. And stubbing "saving" functionality is very hackish now (i try to use it with redux-persist).

Using redux-auth fetch to call async api server side

I am successfully using this library inside of an express/redux/react app to authenticate against a separate rails app with your devise_token_auth gem. Its awesome and works great! I have run into a snag though when trying to get server side rendering of the redux/react app going.

Basically, the promise returned by the redux-auth wrapped version of fetch is not hitting the rails api server and is not resolving. This causes the express server to hang. If I switch it out for "straight-up" isomorphic-fetch, the request is made to the rails api and the promise resolves - I have to disable auth for this to work though. Obviously not a usable solution in production lol.

Any idea why this might be? Is there something special I need to do for redux/auth's fetch to be able to do its job? Could it be that it can't get at the auth data in redux when on the server?

Cannot read property 'getIn' of undefined

I'm getting error when rendering

<OAuthSignInButton
          provider=...
          endpoint=... />

I'm specifying both required provider and endpoint props, but I get this error:

Uncaught TypeError: Cannot read property 'getIn' of undefined

Add `next` param for success redirects.

OAuthSignInButton, EmailSignInForm, and SignOutButton all need support for next param. For example:

<EmailSignInForm next="/my-account" />

In the example above, the user will be redirect to the /my-account path upon successful login.

HMR not working with Redux-Auth

Hey, not sure how to debug this.

But whenever I use HMR. I get this following issue:

This happened after implementing redux-auth

[HMR] The following modules couldn't be hot updated: (They would need a full reload!)

fetch not working in dispatch

Am I doing something wrong? I'm calling redux-auths fetch function to retrieve all user information in our format from our REST API, but it's not authenticating properly. I swear it was working, what's wrong now?

Started GET "/users/me" for ::1 at 2016-08-04 20:42:00 +0200
Processing by UsersController#show as JSON
  Parameters: {"user_id"=>"me", "user"=>{}}
[active_model_serializers] Rendered ActiveModel::Serializer::Null with Hash (0.0ms)
Filter chain halted as :authenticate_user! rendered or redirected
Completed 401 Unauthorized in 6ms (Views: 3.2ms | ActiveRecord: 0.0ms)
export function fetchUser(id = 'me') {
  return function (dispatch) {
    dispatch(requestUser(id))

    return fetch(`http://localhost:3000/users/${id}`, {
      headers: {
        "Accept": "application/json",
        "Content-Type": "application/json"
      }})
      .then(response => response.json())
      .then(json =>
        console.log(json)
        //dispatch(receiveUser(id, json))
      )
  }
}
...
componentDidMount(){
    this.props.loadSettings();
  }
...

UserSettings = reduxForm({
  form: 'user',
  fields: ['username', 'email']
},
state => ({
  initialValues: state.user.currentUser,
  user: state.user.currentUser
}),
{
  loadSettings: fetchUser
})(UserSettings)

export default UserSettings;

Edit: I found out that the token header is sent, but the token itself is undefined.

OAuth 1.0 request token?

Twitter requires apps (consumers) to acquire a request token (shown to client) and request token secret (hidden from client) before apps can be authorised. I was wondering if that's something redux-auth supports and how it does so.

server side code ?

Hi, first of all, awesome project!
Is there an example of the api code somewhere? I can't seem to find it.

Using browserfy

Hello, i wanted to use the library and wanted to try the sing up with the material-ui theme,
i was wondering if the require argument would be the same, and if it is recommended to use it
on the aplication.js file (top level) or using it directly in the component file would work.
import { EmailSignUpForm } from "redux-auth/material-ui-theme";
to something like
EmailSignUpForm = require("redux-auth/material-ui-theme"); would work? i know that inside the material ui theme there are many things, so i am not sure how would that work. I am still learning so any advice is appreciated.

Edit: Maybe i need to give more information to get where i need to be.
I am making a project using flux,react-router, and browserify. I am trying to import the library and use the sign up component, i got to the point where i installed redux-router to fix and issue with a library, and tried making the require as i wrote up, but now i get an error saying ajax ain't supported by this browser when prerendering, i don't know if this is something wrong with my require, the library, or something else.

session storage not persisting

I'm not using server side rendering at the moment, also the server that serves my client is separate from the api server which handles the auth. Does that have any affect on the session storage persisting after refreshing the page? shouldn't the user still be signed in? at the moment it resets the local storage.

Question: How this lib would work with dynamic subdomains

Hi all,
I'm currently developing a rails project that users devise_token_auth gem and apartment gem as well, for multi-tenancy.

The thing is, apartment gem offers this feature os setting your desired tenant with subdomains, and looking at the docs I see that you set the your API as a constant in the configuration of the app.

I'm curious to know if there's a easy workaround for this. Any suggestions? Thanks in advance!

Compability

Sorry because i know this is not an issue, but i was wondering if this lib could be used along a flux architecture if the dependencies got installed. Or is this library only for redux. Soungs like a silly question but i have a flux app and this library would come very handy.
Thanks.

r is not a function

I'm trying to integrate this into react-redux-starter-kit and when injecting the reducer, it's giving me the error that r is not a function.

// reducers.js
...
const auth = configureAuth(
  {apiUrl: 'http://localhost:3000'},
  {serverSideRendering: false, cleanSession: true, clientOnly: true}
);

export const makeRootReducer = (asyncReducers) => {
  return combineReducers({
    form: formReducer,
    auth,
    router,
    ...asyncReducers
  })
}

...

// main.js
...
let render = (routerKey = null) => {
  const routes = require('./routes/index').default(store)

  ReactDOM.render(
    <div>
      <AuthGlobals />
      <AppContainer
        store={store}
        history={history}
        routes={routes}
        routerKey={routerKey}
      />
    </div>,
    MOUNT_NODE
  )
}
...

Maybe I'm doing this all wrong. If so, please tell me how to do it the right way.

https://github.com/davezuko/react-redux-starter-kit

Wrong Request Method

The forms try to send the request with "OPTIONS" method, but my Rails API can't find a route to match that. I'm not sure if I'm doing something wrong, but it's not working, I'm getting this error:

Started OPTIONS "/auth/sign_in" for ::1 at 2016-04-03 22:57:00 +0200
ActionController::RoutingError (No route matches [OPTIONS] "/auth/sign_in")
...

Using standard devise_token_auth gem.

Edit: Seems this issue could be on my end, due to local CORS. Does anyone know a solution anyway?

addComponentAsRefTo error after sign up/sign in success and error

Uncaught (in promise) Error: addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's `render` method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).(…)

This is catched by this code in email-signup-actions

    function emailSignUp(body, endpointKey) {
      console.log('signinup');
      return function (dispatch) {
        dispatch(emailSignUpStart(endpointKey));

        return (0, _fetch2.default)((0, _sessionStorage.getEmailSignUpUrl)(endpointKey), {
          headers: {
            "Accept": "application/json",
            "Content-Type": "application/json"
          },
          method: "post",
          body: (0, _stringify2.default)((0, _extend2.default)(body, {
            confirm_success_url: (0, _sessionStorage.getConfirmationSuccessUrl)()
          }))
        }).then(_handleFetchResponse.parseResponse).then(function (_ref) {
          var data = _ref.data;
          return dispatch(emailSignUpComplete(data, endpointKey));
        }).catch(function (errors) {
          console.log(errors);dispatch(emailSignUpError(errors, endpointKey));
        });

Apparently there is an error thrown somewhere but I can't figure where and why.

DRY up themes

There is a lot of repetition in each of the themes.

  1. factor out things like getEndpoint into shared module.
  2. try to extend as much as possible from the default themes.

Custom submit labels

We've always used the terms "Log in" and "Register" for our apps, so it's more distinguishable. I wanted to set that custom label for the submit button in EmailSignInForm, but apparently that's not possible. Those lines could just be replaced by {this.props.inputProps.submit.text || 'Sign In'}, right?

PS: You don't have some TypeScript definition files lying around for this project, do you? :)

Have a good one!

document is not defined

When I installed this module and tried to run a simple test I got this error document is not defined which came from here

I'm using the default theme

Dependency tree :
rc-dialog/rc-animate/css-animation

Luckily, css-animation is required as 1.x by rc-animation so the issue will be fixed if my PR is merged.

  "dependencies": {
    "css-animation": "1.x"
  }

npm install gives "UNMET PEER DEPENDENCY [email protected]"

Running: $ npm install --save redux-auth

> [email protected] postinstall /Users/albertorocha/Dropbox/code/frontend-newin/node_modules/redux-auth/node_modules/history
> node ./npm-scripts/postinstall.js


> [email protected] postinstall /Users/albertorocha/Dropbox/code/frontend-newin/node_modules/redux-auth/node_modules/react-router
> node ./npm-scripts/postinstall.js

[email protected] /Users/albertorocha/Dropbox/code/frontend-newin
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── UNMET PEER DEPENDENCY [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └─┬ [email protected]
│ │ │   └─┬ [email protected]
│ │ │     └── [email protected]
│ │ └─┬ [email protected]
│ │   ├── [email protected]
│ │   └─┬ [email protected]
│ │     └─┬ [email protected]
│ │       ├── [email protected]
│ │       ├── [email protected]
│ │       └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│   └── [email protected]
└─┬ [email protected]
  └─┬ [email protected]
    └─┬ [email protected]
      └─┬ [email protected]
        └─┬ [email protected]
          └─┬ [email protected]
            └── [email protected]

npm WARN [email protected] requires a peer of history@^1.17.0 but none was installed.
npm WARN In [email protected] replacing bundled version of history with [email protected]

BTW, I'm new in the world of npm and react
Give me a hint and I'll create a pull request :)
Any suggestion?

Couldn't load authHeaders in client-side rendering

I'm looking into a way to keep user session alive so that user doesn't have to login again next time visiting the site. My site is using client-side rendering. After tracing the code, I figured out that there might be a chance to load session from localStorage to accomplish the goal. I'm not sure if this a good way and would like to get some feedback here.

In action/configure.js

      if (authRedirectPath) {
        dispatch(push({pathname: authRedirectPath}));
      }

      if (authRedirectHeaders && authRedirectHeaders.uid && authRedirectHeaders["access-token"]) {
        settings.initialCredentials = extend({}, settings.initialCredentials, authRedirectHeaders);
      }

      /*  Maybe check localStorage before destroying session */

      // if tokens were invalidated by server, make sure to clear browser
      // credentials
      if (!settings.initialCredentials) {
        destroySession();
      }

Don't depend on ImmutableJS

Not everyone uses ImmutableJS, and requiring it adds a 57KB minified chunk of code to the initial download.

There is so little data in the auth reducer that ImmutableJS only adds overhead, with very little benefit. Would you consider dropping the dependency? You can use Object.assign or simply the ... spread operator for merging state into a new object.

Unmet peer dependencies

Hi, I'm getting the following error when attempting to install this module.

npm info postinstall [email protected]
npm WARN unmet dependency C:\Users\bescott\Work\QE\viu-fe\node_modules\redux-auth\node_modules\redux-router\node_modules\history requires query-string@'^3.0.0' but will load npm WARN unmet dependency C:\Users\bescott\Work\QE\viu-fe\node_modules\redux-auth\node_modules\query-string,
npm WARN unmet dependency which is version 2.4.2
npm ERR! Windows_NT 6.1.7601
npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "redux-auth" "--save"
npm ERR! node v4.4.0
npm ERR! npm  v2.14.20
npm ERR! code EPEERINVALID

npm ERR! peerinvalid The package [email protected] does not satisfy its siblings' peerDependencies requirements!
npm ERR! peerinvalid Peer [email protected] wants history@^1.17.0

npm ERR! Please include the following file with any support request:
npm ERR!     C:\Users\bescott\Work\QE\viu-fe\npm-debug.log

`renderApp()` function not returning a `.then()` promise (returns undefined)

//Render App
RenderApp().then(appComponent => {
  ReactDOM.render(appComponent, document.getElementById('root'))
})

Logs:

index.js:21 Uncaught TypeError: Cannot read property 'then' of undefined

The function:

RenderApp()

returns undefined:
The render app function is as follows:

module.exports = function ({cookies, isServer, currentLocation} = {}) {
  store.dispatch(
    configure (
      {
        apiUrl: "http://api.x.com",
      },
      {
        isServer,
        cookies,
        currentLocation
      }
    )
  )
  .then(
    function () {
      return (
        <Provider store={store}>
          <AppContainer>
            <Router history={browserHistory}>
              <Route path="/" component={Index}/>
              <Route path="*" component={NoMatch}/>
            </Router>
          </AppContainer>
        </Provider>
      )
    }
  )
}

Would love some feedback.

Warning on Critical Dependency

I built brand new project with a starter kit after adding EmailSignupForm (or any other) i am getting this error
material-ui-theme.js?0449:1 Uncaught TypeError: Cannot read property 'getIn' of undefined

And on my console
WARNING in .//encoding/lib/encoding.js
Critical dependencies:
9:12-34 the request of a dependency is an expression
@ ./
/encoding/lib/encoding.js 9:12-34

Credentials not saved on login

Hi there! Thanks for the hard work on this project, just browsing the source has already helped me a bunch. Unfortunately, however, I can't seem to get this to function correctly when validating on my fake API.

The problem I am experiencing is that when I attempt a sign_in action, the react app is authenticated, however if I refresh the page the state does not persist. I have read through issue #50 and this may be part of the problem however I have noticed that the auth-token doesn't actually get read (and therefore is never saved).

Specifically, in utils/fetch.js when updateAuthCredentials is called, the resp.headers object doesn't contain any values (so persisData doesn't get called further down)

The following is my current (fake/testing) node api server, which seems to responds with the correct headers when I hit it with postman. What am I missing?

var jsonServer = require('json-server')
var R = require('ramda')
var faker = require('faker')
var nLoop = R.range(0)
var util = require('util')
const jwt = require('jsonwebtoken')
const moment = require('moment')

function aPerson() {
    return {
        first: faker.name.firstName(),
        last: faker.name.lastName(),
        phone: faker.phone.phoneNumber(),
        email: faker.internet.email()
    }
}

var data = {
        users: nLoop(10).map(aPerson)
}

var server = jsonServer.create()
var router = jsonServer.router(data)
var middlewares = jsonServer.defaults()

// Set default middlewares (logger, static, cors and no-cache)
server.use(middlewares)

server.set('jwtTokenSecret', 'bgINB4atOxd8SMNvtOTDxg')
server.set('userId', '[email protected]')

var expires = moment().add('days', 7).valueOf()
var token = jwt.sign({ 
    iss: server.get('userId'),
    exp: expires
}, server.get('jwtTokenSecret'))

// Add custom routes before JSON Server router
server.get('/echo', function (req, res) {
    res.jsonp(req.query)
})

server.post('/auth/validate_token/', (req, res) => {
    if (req.body.email == '[email protected]' && req.body.password == 'test') {
        res.status(200)
                .json({token: token})
    } else {
        res.sendStatus(403)
    }
})


server.post('/auth/sign_in', function (req, res) {
    res.set({
        'Expires':      expires,
        'access-token': token,
        'token-type':   'Bearer',
        'expiry':       expires,
        'client':       'V7EN7LSRYAbpE_-c5PvRSw',
        'uid':          server.get('userId')
    })

    res.json({
        "data": {
            "uid": server.get('userId'),
            "provider": "email",
            "email": server.get('userId'),
            "favorite_color": null,
            "id": 6
        }
    })
})

server.delete('/auth/sign_out', function (req, res) {
    res.json({ "success": true })
})


// Use default router
server.use(router)
server.listen(3010, function () {
    console.log('JSON Server is running on localhost:3010')
})

headers from postman:

Access-Control-Allow-Credentials →true
Access-Control-Allow-Origin →chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop
Cache-Control →no-cache
Connection →keep-alive
Content-Length →142
Content-Type →application/json; charset=utf-8
Date →Fri, 20 May 2016 22:54:17 GMT
ETag →W/"8e-rSsVlXMHretJT9EANZhtxA"
Expires →1464389523686
Pragma →no-cache
Vary →Origin, Accept-Encoding
X-Powered-By →Express
access-token →eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0ZXN0QHRlc3QuY29tIiwiZXhwIjoxNDY0Mzg5NTIzNjg2LCJpYXQiOjE0NjM3ODQ3MjN9.p2QnbB8E7_NdyOo3lv1MKrjT383gA_DMO1k7GbZdlGI
client →V7EN7LSRYAbpE_-c5PvRSw
expiry →1464389523686
token-type →Bearer
uid →[email protected]

Would looooove some insight into this as I'm super stumped.

Accessing auth state from a different reducer

Is there a way for me to access the auth state from a different reducer?

I'm trying to update User information when user's edit their profile, but I can't access or set user information from the auth state if I'm not in the authReducer. And there's no component available that allows users to edit their information (with the exception of password). Does anyone have a work around or suggestions?

Uncaught TypeError: E is not a function on OAuthSignInButton click

hello guys! I tried to setup application. According to example https://github.com/lynndylanhurley/redux-auth-demo (setup configure and authStateReducer)

But got such error on <DefaultTheme.OAuthSignInButton/> button click.

Uncaught TypeError: E is not a function
s.value @ index.js:formatted:4708
s.value @ index.js:formatted:1036
ReactErrorUtils.invokeGuardedCallback @ ReactErrorUtils.js:71
executeDispatch @ EventPluginUtils.js:79
executeDispatchesInOrder @ EventPluginUtils.js:102
executeDispatchesAndRelease @ EventPluginHub.js:43
executeDispatchesAndReleaseTopLevel @ EventPluginHub.js:54
forEachAccumulated @ forEachAccumulated.js:23
EventPluginHub.processEventQueue @ EventPluginHub.js:259
runEventQueueInBatch @ ReactEventEmitterMixin.js:18
ReactEventEmitterMixin.handleTopLevel @ ReactEventEmitterMixin.js:34
handleTopLevelWithoutPath @ ReactEventListener.js:93
handleTopLevelImpl @ ReactEventListener.js:73
Mixin.perform @ Transaction.js:136
ReactDefaultBatchingStrategy.batchedUpdates @ ReactDefaultBatchingStrategy.js:62
batchedUpdates @ ReactUpdates.js:94
ReactEventListener.dispatchEvent @ ReactEventListener.js:204

so error is fired here:
redux-auth/index.js

{
    key: "handleClick",
    value: function() {
        this.props.dispatch(E({
            provider: this.props.provider,
            params: this.props.signInParams,
            endpointKey: this.getEndpoint()
        }))
    }
}

what is minified version of

https://github.com/lynndylanhurley/redux-auth/blob/master/src/views/default/OAuthSignInButton.js#L32

handleClick () {
  this.props.dispatch(oAuthSignIn({
    provider: this.props.provider,
    params: this.props.signInParams,
    endpointKey: this.getEndpoint()
  }));
}

and looks like oAuthSignIn is missed, but I don't get how is it possible.

PS

in the same time I can build demo example (https://github.com/lynndylanhurley/redux-auth-demo) and click OAuthSignInButton there without any problem

Question: http/https SecurityError in popup. Am I approaching wrong?

This might be a question for StackOverflow and if you'd like me to post there I'd be happy to. I used redux-auth as a guide to setting up OAuth though so I thought someone here might be able to answer my question with better context...

So I'm trying to do google oauth to get a refresh token for my users (not actually using google oauth to save the user). I had everything working when I used the client side OAuth for google api but they don't provide a refresh token when you do that handshake, only an access_token. So I set up omniauth on my rails server to make the flow go like this:

user clicks authenticate with google --> popup in screen goes to backend server --> backend server redirects to google oauth --> they authenticate and get redirected to backend server's callback --> backend server saves token for appropriate user and then redirects back to client side app on localhost:3000 (nothing needs to be done on client, just need the token saved on my server)

I do however need to know that the authentication was successful so I can dispatch appropriate actions. In redux-auth you check for the access_token inside the popup.location URI. Problem is when I use this server side popup flow I get this nasty http/https error:

screen shot 2016-01-31 at 7 44 03 pm

If instead of redirecting back to the client I just redirect to a view in my backend server I could then have a script on that page that just does window.close() but that seems hacky to me. Another potential solution I was thinking was to try and use the window.postMessage api but I don't know if that has great browser support/also seems hacky.

I feel like I'm just approaching this whole flow completely wrong or I'm missing something obvious. If anyone has any thoughts or could give me some direction that would be much appreciated!!

Design Module to persist credentials properly

I have patched the code with a npm module redux-auth-patch.
It appears there are some issues with persisting authHeaders in the cookies.

the isApiRequest() will break if you do not clear cookies upon new entry.

I'd also suggest a more procedural type approach to the session-storage.js file. It was quite confusing tracing the issue and then identifying that the issue was in fact in fetch.js not session-storage.js.

Custom REST Calls - (Needs PR?)

I'm looking at the fetch request and noticed I can't do anything except GET requests.

Is there some way to add a custom method and body to the fetch request? I would like to know if that's possible. (Based on what I'm looking at in ./src/utils/fetch.js I need to refactor with multiple params.

event is not defined on handleSubmit() of EmailSignUpForm

Code:

class RightColumn extends React.Component {
  render() {
    return (
      <div className="right-column">
        <div>
          <EmailSignUpForm
            endpoint={"http://localhost:3000/api/"}
          />
        </div>
      </div>
    );
  }
}

The console outputs the following when I click submit

submitting form to endpoint http://localhost:3000/api/
Uncaught TypeError: Cannot read property 'preventDefault' of undefined

I looked at https://github.com/lynndylanhurley/redux-auth/blob/c7dcc300ef23daf2deabdc7f7a18177124dc5dcb/src/views/default/EmailSignUpForm.js but the code seems fine. Do you think you can try to repro it on your end too?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.