4

I use mac to develop a MEAN stack project. My web pages https://localhost:3000/#/login and https://localhost:3000/#/new work (note that all my pages need to have /#/ in the middle to work). https://localhost:3000/#/new has a button that leads to a google login by passportjs. In my routes ==> index.js I set

var express = require('express');
var router = express.Router();
... ...

router.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] }));
router.get('/auth/google/callback',
  passport.authenticate('google', { successRedirect: '/login',
                                    failureRedirect: '/login' }));

In Google APIs ==> Credentials, when I set https://localhost:3000/auth/google/callback as Authorized redirect URIs. Clicking on the login button on my page returns an error

Error: redirect_uri_mismatch

The redirect URI in the request, https://localhost:3000/auth/facebook/callback, does not match the ones authorized for the OAuth client. Visit https://console.developers.google.com/apis/credentials/oauthclient/367100934152-7csfhcdnkapil4obku1pr2cnrsmthk61.apps.googleusercontent.com?project=367100934152 to update the authorized redirect URIs.

I guess it is because https://localhost:3000/auth/facebook/callback is not a valid URI for my app, but if I set https://localhost:3000/#/auth/facebook/callback in the setting page, it is NOT allowed: Invalid Redirect: https://localhost:3000/#/auth/google/callback cannot contain a fragment.

So, does anyone know if I could modify my app to work without #, so that https://localhost:3000/login and https://localhost:3000/new, etc. will work? As a result, https://localhost:3000/auth/facebook/callback will be a valid URI too...

Edit 1:

Following the answer of @Sevran and the doc how to configure your server to work with html5mode, I did the following:

1) added $locationProvider.html5Mode(true) in app.config

2) added <base href="/" /> in index.ejs (note I don't have index.html in the project)

3) keeps .state('new', url: '/new', ... in app.config

4) did NOTHING in httpd-vhosts.conf, which has <VirtualHost *:80> and <VirtualHost *:433>, because I think my server is controlled by express.js rather than httpd-vhosts.conf, and the port is 3000.

5) did NOT add .htaccess in the project like this answer

6) added in app.js the following, I also tried to change index.html to index.ejs.

app.use('/js', express.static(__dirname + '/js'));
app.use('/dist', express.static(__dirname + '/../dist'));
app.use('/css', express.static(__dirname + '/css'));
app.use('/partials', express.static(__dirname + '/partials'));

app.all('/*', function(req, res, next) {
    // Just send the index.html for other files to support HTML5Mode
    res.sendFile('index.html', { root: __dirname });
});

The tests shows

  1. entering https://localhost:3000/#/new in the URL bar becomes https://localhost:3000/new, and it loads the corresponding page.

  2. entering https://localhost:3000/new in the URL bar raises a not found 404 error.

  3. entering https://localhost:3000/auth/google in the URL bar raises the Error: redirect_uri_mismatch as above.

To conclude, I think the rewriting (of a url without #) should be managed by express, but the code I posted did not do the job. Regarding .htaccess, I tried also to put it in the DocumentRoot of httpd-vhosts.conf or the root folder of the project, it did not help.

Community
  • 1
  • 1
SoftTimur
  • 5,630
  • 38
  • 140
  • 292
  • Are you using angularjs for front-end ? – Love-Kesh Mar 28 '17 at 04:59
  • Yes, I use mean stack: angularjs for front-end... – SoftTimur Mar 28 '17 at 05:00
  • https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode, check this link, you have to set the virtual host and point the directory to root folder of the application. – Sravan Mar 30 '17 at 10:31

3 Answers3

1

In app->init.js enable below mode in config

 $locationProvider.html5Mode({
      enabled: true,
      requireBase: false
    }).hashPrefix('!');
Love-Kesh
  • 777
  • 7
  • 17
  • I did this, then `https://localhost:3000/#/new` becomes `https://localhost:3000/#%2Fnew` and shows a blank page; `https://localhost:3000/new` raises a `Not found 404` error. – SoftTimur Mar 28 '17 at 05:28
  • href should be like this href="/#!/new" – Love-Kesh Mar 28 '17 at 05:31
  • I changed `.state('new', { url: '/new', ... }` to `.state('new', { url: '/#!/new', ...}`, it is still the same thing... – SoftTimur Mar 28 '17 at 05:55
1

You can remove the hash from your URL using the HTML5 mode:

appModule.config(['$locationProvider', function($locationProvider) {
    $locationProvider.html5Mode(true);
}]);

Don't forget to set the base in your <head> tag:

<head>
    <base href="/">
    ...
</head>

Note that if you are using Angular 1.6, you also need to change the hashPrefix:

appModule.config(['$locationProvider', function($locationProvider) {
    $locationProvider.html5Mode(true);
    $locationProvider.hashPrefix(''); // remove the ! from URL
}]);

More info about the changelog here.

Community
  • 1
  • 1
Mistalis
  • 17,793
  • 13
  • 73
  • 97
  • This is almost what I did in `Edit 1`, right? I added `$locationProvider.hashPrefix('')`, but the problem is still there... – SoftTimur Mar 30 '17 at 10:13
1

The changes you have to make:

1) Angular Side: as you already changed

$locationProvider.html5Mode(true) in app.config

added <base href="/" /> in index.ejs

keeps .state('new', url: '/new', ... in app.config

2) hta access

RewriteEngine   On
RewriteBase     /
RewriteCond     %{REQUEST_URI} !^(/index\.php|/img|/js|/css|/robots\.txt|/favicon\.ico)
RewriteCond     %{REQUEST_FILENAME} !-f
RewriteCond     %{REQUEST_FILENAME} !-d
RewriteRule     ./index.html [L]

3) This change you need from server side,

If using apache:

<VirtualHost *:80>
    ServerName my-app

    DocumentRoot /path/to/app

    <Directory /path/to/app>
        RewriteEngine on

        # Don't rewrite files or directories
        RewriteCond %{REQUEST_FILENAME} -f [OR]
        RewriteCond %{REQUEST_FILENAME} -d
        RewriteRule ^ - [L]

        # Rewrite everything else to index.html to allow html5 state links
        RewriteRule ^ index.html [L]
    </Directory>
</VirtualHost>

In the above my-app will be the application name. and DocumentRoot and Directory paths should be complete path to your application root

For Express:

var express = require('express');
var app = express();

app.use('/js', express.static(__dirname + '/js'));
app.use('/dist', express.static(__dirname + '/../dist'));
app.use('/css', express.static(__dirname + '/css'));
app.use('/partials', express.static(__dirname + '/partials'));

app.all('/*', function(req, res, next) {
    // Just send the index.html for other files to support HTML5Mode
    res.sendFile('index.html', { root: __dirname });
});

app.listen(3006); //the port you want to use

Here is the Documentation regarding it

Sravan
  • 18,467
  • 3
  • 30
  • 54
  • I'm testing it... i think if I do the necessary for `express`, the configuration in `apache` is not necessary, right? neither the `.htaccess`? – SoftTimur Mar 30 '17 at 11:01
  • yes, `.htaccess` change is not required, I am not much aware if `.htaccess`, make change in `apache`, I think it will serve your purpose – Sravan Mar 30 '17 at 11:04
  • change either `express` or `apache` not both. Also, you should create a new `hosts` file, and enable it. – Sravan Mar 30 '17 at 11:28
  • you mean I should create another `httpd-vhosts.conf`? – SoftTimur Mar 30 '17 at 11:31
  • yes, create a new conf file, and enable it using sites-enable feature – Sravan Mar 30 '17 at 11:38
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/139486/discussion-between-sravan-and-softtimur). – Sravan Mar 30 '17 at 11:38