I have a Sinatra-based server which provides RESTful API for the service I'm working on. On my development machine in runs on localhost:9393
.
At the same time my client application (built with ember.js
) which uses ember-auth
for user authentication runs on another port: localhost:9000
.
Previously I set up both server and client on the same host:port and returned client app as static files. Authentication worked pretty well. According to the official docs on SignIn I get POST request on the route I provided (/signin
). But now I recieve OPTIONS request with no params whatsoever.
Some code from client (client is generated via Yeoman's ember-generator):
index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>Ember Starter Kit</title>
<!-- build:css styles/main.css -->
<link rel="stylesheet" href="styles/normalize.css">
<link rel="stylesheet" href="styles/bootstrap.css">
<link rel="stylesheet" href="styles/bootstrap-responsive.css">
<link rel="stylesheet" href="styles/style.css">
<!-- endbuild -->
</head>
<body>
<!-- build:js scripts/components.js -->
<script src="components/jquery/jquery.js"></script>
<script src="components/handlebars/handlebars.runtime.js"></script>
<script src="components/ember/ember.js"></script>
<script src="components/ember-data/ember-data-latest.js"></script>
<script src="components/ember-auth/ember-auth.js"></script>
<!-- endbuild -->
<!-- build:js scripts/main.js -->
<script src="scripts/app.js"></script>
<script src="scripts/models/user.js"></script>
<script src="scripts/views/auth.js"></script>
<!-- endbuild -->
<!-- build:js(.tmp) scripts/templates.js -->
<script src="scripts/compiled-templates.js"></script>
<!-- endbuild -->
</body>
</html>
app.js
var App = window.App = Ember.Application.create();
App.Store = DS.Store.extend({
revision: 12,
adapter:'DS.RESTAdapter'
});
App.Router.map(function() {
// I have no routes so far,
// as I don't need them to test authentication itself
});
App.Auth = Ember.Auth.create({
signInEndPoint: '/signin',
signOutEndPoint: '/signout',
tokenKey: 'auth_token',
baseUrl: 'http://localhost:9393',
tokenIdKey: 'user_id',
userModel: 'App.User',
sessionAdapter: 'cookie',
modules: [
'emberData', 'rememberable'
],
rememberable: {
tokenKey: 'remember_token',
period: 7,
autoRecall: true
}
});
user.js
App.User = DS.Model.extend({
email: DS.attr('string'),
param: DS.attr('string')
});
auth.js
App.AuthView = Ember.View.extend({
templateName: 'auth'
});
App.AuthSignInView = Ember.View.extend({
templateName: 'signin',
email: null,
password: null,
remember: true,
submit: function(event, view){
event.preventDefault();
event.stopPropagation();
App.Auth.signIn({
data:{
email: this.get('email'),
password: this.get('password'),
remember: this.get('remember')
}
})
}
});
App.AuthSignOutView = Ember.View.extend({
templateName: 'signout',
submit: function(event, view){
event.preventDefault();
event.stopPropagation();
App.Auth.signOut();
}
});
application.hbs
<div class="container">
<div class="row">
<div class="span3">
{{view App.AuthView}}
</div>
<div class="span9">
{{outlet}}
</div>
</div>
</div>
auth.hbs
{{#if App.Auth.signedIn}}
{{view App.AuthSignOutView}}
{{else}}
{{view App.AuthSignInView}}
{{/if}}
signin.hbs
<form>
<label>Email</label>
{{view Ember.TextField valueBinding="view.email"}}
<label>Password</label>
{{view Ember.TextField type='password' valueBinding="view.password"}}
{{view Ember.Checkbox checkedBinding="view.remember"}}
<label>Remember me?</label>
<hr />
<button type="submit">Sign In</button>
</form>
Your REST API and client app are served from different origins; the protocol, host and port must be identical to follow same-origin policy. Your browser is making a preflight OPTIONS request to determine if your server will allow cross-origin resource sharing (CORS) from your client domain.
To get CORS working with your Sinatra server, you might want to check out rack-cors which will allow you to add middleware for setting the requisite access control headers. Once that is set up correctly, the expected POST request will be issued following the successful OPTIONS request.
For more on CORS, here are some resources I've found useful:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With