EmberJS simpleauth with devise authorizer not sending token header - ruby-on-rails

I can't figure out how to get ember-simple-auth with ember-simple-auth-devise authorizer (version 0.7.2) to append the token header to my backend requests.
Here is how my config/environment.js looks:
var ENV = {
modulePrefix: 'frontend-app',
environment: environment,
baseURL: '/',
locationType: 'auto',
EmberENV: {
FEATURES: {}
},
APP: {},
'simple-auth': {
authenticationRoute: 'sign-in',
authorizer: 'simple-auth-authorizer:devise'
}
};
if (environment === 'development') {
// ENV.APP.LOG_RESOLVER = true;
// ENV.APP.LOG_ACTIVE_GENERATION = true;
ENV.APP.LOG_TRANSITIONS = true;
// ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
// ENV.APP.LOG_VIEW_LOOKUPS = true;
ENV.contentSecurityPolicy = {
'font-src': "'self' http://fonts.gstatic.com",
'style-src': "'self' 'unsafe-inline' http://fonts.googleapis.com",
'connect-src': "'self' http://localhost:3000",
};
ENV['simple-auth-devise'] = {
serverTokenEndpoint: "//localhost:3000/users/sign_in"
};
ENV.apiHost = "http://localhost:3000";
}
I was able to get authentication working, I get a session object in my application. Here are the headers from a successful exchange with the session endpoint:
POST /users/sign_in HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Content-Length: 63
Accept: application/json, text/javascript
Origin: http://localhost:4200
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:4200/sign-in
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
And the server responds with this session object:
{"user_token":"eo2xxzYsQ6UifMKvoLMF","user_id":3,"user_email":"snip#snip.com","user_first_name":"Xavier","user_last_name":"Lange"}
But all subsequent requests don't set the header:
GET /api/reports?user_id=3 HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Cache-Control: max-age=0
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://localhost:4200
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36
Referer: http://localhost:4200/reports
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
If-None-Match: W/"8e1b98de900ac194a0bc3ef6e9dc7459"
Where I should expect
Authorization: Token token="<token>", email="<email>"
to be in the headers sent to the backend. But it's not happening.

The issue was solved by checking the crossOriginWhitelist in development:
if (environment === 'development') {
// ENV.APP.LOG_RESOLVER = true;
// ENV.APP.LOG_ACTIVE_GENERATION = true;
ENV.APP.LOG_TRANSITIONS = true;
// ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
// ENV.APP.LOG_VIEW_LOOKUPS = true;
ENV.contentSecurityPolicy = {
'font-src': "'self' http://fonts.gstatic.com",
'style-src': "'self' 'unsafe-inline' http://fonts.googleapis.com",
'connect-src': "'self' http://localhost:3000",
};
ENV['simple-auth']['crossOriginWhitelist'] = ['http://localhost:3000'];
ENV['simple-auth-devise']['serverTokenEndpoint'] = "//localhost:3000/users/sign_in"
ENV.apiHost = "http://localhost:3000";
}
Then I had to change simple-auth-devise to use email as the identification property (rails was having a hardtime parsing the Authorization header with authenticate_with_http_token:
var ENV = {
modulePrefix: 'my-app',
environment: environment,
baseURL: '/',
locationType: 'auto',
EmberENV: {
FEATURES: {
// Here you can enable experimental features on an ember canary build
// e.g. 'with-controller': true
}
},
APP: {
// Here you can pass flags/options to your application instance
// when it is created
},
'simple-auth': {
authenticationRoute: 'sign-in',
authorizer: 'simple-auth-authorizer:devise'
},
'simple-auth-devise': {
identificationAttributeName: 'email'
}
};
And my session serializer had to sync up with that attribute name:
class SessionsController < Devise::SessionsController
skip_before_action :authenticate_user_from_token!, only: [:create]
def create
respond_to do |format|
format.json do
self.resource = warden.authenticate!(auth_options)
sign_in(resource_name, resource)
data = {
token: self.resource.authentication_token,
user_id: self.resource.id,
email: self.resource.email,
user_first_name: self.resource.first_name,
user_last_name: self.resource.last_name
}
render json: data, status: 201
end
end
end
end

Related

Sberbank balance parsing

I was trying to parse my balance from sberbank.ru
So here is what i've tried
import requests
headers = {
'Cookie': 'cookie',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.132 YaBrowser/22.3.1.895 Yowser/2.5 Safari/537.36',
}
params = {
'forceUpdate': 'false',
'withData': 'true'
}
resp_json = requests.post('https://web-node6.online.sberbank.ru/main-screen/rest/v1/web/section/meta', headers=headers, params=params).json()
print(resp_json)
But i got this error
{'status': {'code': 3, 'errors': [{'id': 'EFSGW-41', 'element': '', 'title': 'datapower', 'description': 'Ошибка валидации запроса'}], 'warnings': [{'id': '', 'element': '', 'title': '', 'description': ''}]}}

springdoc / Swagger UI not passing OAuth2 token to API

I am using springdoc (v1.5.9) to generate Swagger definitions for an API. After authenticating inside the Swagger UI and executing a secured method, the http request received by the Spring Boot app has no Authentication header. I have confirmed via JS debugger that the Swagger UI received and stored a valid authentication token.
Below are the HTTP request, the Swagger api-docs showing the security scheme defined / applied to the method, the springdoc configuration and a controller.
How do I need to change / add to my Spring configuration to get the Authorization passed to the API from the Swagger UI?
HTTP request received
Request received for GET '/foo/1234':
org.apache.catalina.connector.RequestFacade#71c70030
servletPath:/foo/1234
pathInfo:null
headers:
host: localhost:8070
connection: keep-alive
sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"
accept: application/json
sec-ch-ua-mobile: ?0
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36
sec-fetch-site: same-origin
sec-fetch-mode: cors
sec-fetch-dest: empty
referer: http://localhost:8070/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
cookie: JSESSIONID=A0F9846102153C06D77D6ED5506CC227
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
BearerTokenAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
api-docs
{
"openapi": "3.0.1",
"info": {
"title": "My App",
"version": "v1"
},
"servers": [
{
"url": "http://localhost:8070",
"description": "Generated server url"
}
],
"paths": {
"/foo/{id}": {
"get": {
"tags": [
"foo"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
},
"security": [
{
"custom": [
]
}
]
}
},
"securitySchemes": {
"access_token": {
"type": "oauth2",
"in": "header",
"scheme": "custom",
"flows": {
"authorizationCode": {
"authorizationUrl": "https://login.myauthsever.com/v2/oauth/authorize",
"tokenUrl": "https://login.myauthsever.com/v2/oauth/token",
"scopes": {
}
}
}
}
}
}
}
OpenAPI config
#OpenAPIDefinition(info = #Info(title = "My App", version = "v1"))
#SecurityScheme(scheme = "custom", type = SecuritySchemeType.OAUTH2, in = SecuritySchemeIn.HEADER, name = "access_token",
flows = #OAuthFlows(authorizationCode = #OAuthFlow(
authorizationUrl = "https://login.myauthsever.com/v2/oauth/authorize",
tokenUrl = "https://login.myauthsever.com/v2/oauth/token", scopes = {})))
public class OpenApiConfig {
}
Controller
#RestController
#Tag(name = "foo")
#SecurityRequirement(name = "custom")
public class SystemSigController {
#GetMapping(path = "/foo/{id}")
String getFoo(#PathVariable String id) {
...
}
}
The #SecurityRequirement.name value must be the same as #SecurityScheme.name.
Since you have #SecurityScheme(..., name = "access_token"...), the controller must use:
#SecurityRequirement(name = "access_token")

Integration test with rest assured and basic auth with CSRF

I have a working Spring Boot with AngularJs app based on https://spring.io/guides/tutorials/spring-security-and-angular-js/
I am using Basic Authentication and I would like to write an integration test for it. Currently, I always get a 403 status code with the message:
Expected CSRF token not found. Has your session expired?
This is my test:
#Test
public void givenAdmin_deleteOfBookIsAllowed() {
Response response = given().auth().preemptive().basic("admin", "admin").get("/api/user/");
response.then().log().all();
String sessionId = response.sessionId();
String token = response.cookie("XSRF-TOKEN");
Book book = Books.randomBook();
bookRepository.save(book);
given()
.sessionId(sessionId)
.cookie("XSRF-TOKEN", token)
.header("X-XSRF-TOKEN", token)
.pathParam("id", book.getId().getId())
.when().delete("/api/books/{id}")
.then().statusCode(HttpStatus.SC_NO_CONTENT);
}
I am using a custom token repo per the tutorial:
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
This is the request/response from the first call:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Set-Cookie: JSESSIONID=7020E58A8D6DC2C883FD5D6BD086512A; Path=/; HttpOnly
Set-Cookie: XSRF-TOKEN=6c44ae09-73f9-4115-bbbf-b01773ec1b91; Path=/
X-Application-Context: application:staging:0
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Content-Encoding: gzip
Vary: Accept-Encoding
Date: Fri, 08 Jan 2016 07:43:21 GMT
{
"details": {
"remoteAddress": "127.0.0.1",
"sessionId": "7020E58A8D6DC2C883FD5D6BD086512A"
},
"authorities": [
{
"authority": "ROLE_ADMIN"
},
{
"authority": "ROLE_USER"
}
],
"authenticated": true,
"principal": {
"password": null,
"username": "admin",
"authorities": [
{
"authority": "ROLE_ADMIN"
},
{
"authority": "ROLE_USER"
}
],
"accountNonExpired": true,
"accountNonLocked": true,
"credentialsNonExpired": true,
"enabled": true
},
"credentials": null,
"name": "admin"
}
And from the second call:
Request method: DELETE
Request path: http://localhost:64588/api/books/04ad6d12-9b59-4ade-9a8a-e45daccb1f61
Proxy: <none>
Request params: <none>
Query params: <none>
Form params: <none>
Path params: id=04ad6d12-9b59-4ade-9a8a-e45daccb1f61
Multiparts: <none>
Headers: X-XSRF-TOKEN=6c44ae09-73f9-4115-bbbf-b01773ec1b91
Accept=*/*
Cookies: JSESSIONID=7020E58A8D6DC2C883FD5D6BD086512A
XSRF-TOKEN=6c44ae09-73f9-4115-bbbf-b01773ec1b91
Body: <none>
HTTP/1.1 403 Forbidden
Server: Apache-Coyote/1.1
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Content-Encoding: gzip
Vary: Accept-Encoding
Date: Fri, 08 Jan 2016 07:44:21 GMT
{
"timestamp": "2016-01-08T07:44:21.963+0000",
"status": 403,
"error": "Forbidden",
"message": "Expected CSRF token not found. Has your session expired?",
"path": "/api/books/04ad6d12-9b59-4ade-9a8a-e45daccb1f61"
}
You need to do 2 GET before post to use spring security CSRF protection in your rest client or integration test.
Make a GET request to login. This will return the JSESSIONID token and XSRF-TOKEN tokens. If you use the returned XSRF-TOKEN to POST it will fail, because we got it using empty/false JSESSIONID.
Get a useful XSRF-TOKEN from the second GET, using JSESSIONID from previous request.
Now you can use XSRF-TOKEN for your POST.
Example integration test for rest assured with basic auth and CSRF protection:
//1) get sessionId
Response response =
given().auth().preemptive().basic(userName, userPassword).contentType(JSON).
when().get(PREFIX_URL + "/user").
then().log().all().extract().response();
String jsessionidId = response.getSessionId();//or response.cookie("JSESSIONID");
//2) get XSRF-TOKEN using new/real sessionId
response =
given().
sessionId(jsessionidId).//or cookie("JSESSIONID", jsessionidId).
contentType(JSON).
when().get(PREFIX_URL + "/user").
then().log().all().extract().response();
//3) post data using XSRF-TOKEN
given().log().all().
sessionId(jsessionidId).//or cookie("JSESSIONID", jsessionidId).
header("X-XSRF-TOKEN", response.cookie("XSRF-TOKEN")).
queryParam("param",paramValue)).
body(someData).
contentType(JSON).
when().
post(PREFIX_URL + "/post_some_data").
then().
log().all().assertThat().statusCode(200);

Grails Spring Security Rest Basic Configuration

I am creating the backend in Grails that needs to support both mobile app & web app.
I have managed to use compile ':spring-security-core:2.0-RC4' for the authentication. It works fine.
Now I want to make it restful for the mobile app to call the api. So I added the following in the BuildConfig.groovy.
compile ":spring-security-rest:1.4.1", {
excludes: 'spring-security-core'
}
I am following this tutorial to use spring-security-rest.
http://alvarosanchez.github.io/grails-spring-security-rest/docs/guide/tokenStorage.html
In my app, I have User domain which extends SecUser.
Here is my Config.grrovy.
// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'm15.authentication.SecUser'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'm15.authentication.SecUserSecRole'
grails.plugin.springsecurity.authority.className = 'm15.authentication.SecRole'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
'/': ['permitAll'],
'/index': ['permitAll'],
'/index.gsp': ['permitAll'],
'/assets/**': ['permitAll'],
'/**/js/**': ['permitAll'],
'/**/css/**': ['permitAll'],
'/**/images/**': ['permitAll'],
'/**/favicon.ico': ['permitAll']
]
grails.plugin.springsecurity.rest.login.active = true
grails.plugin.springsecurity.rest.login.endpointUrl = '/api/login'
grails.plugin.springsecurity.rest.login.failureStatusCode = '401'
grails.plugin.springsecurity.rest.login.useJsonCredentials = true
grails.plugin.springsecurity.rest.login.usernamePropertyName = 'username'
grails.plugin.springsecurity.rest.login.passwordPropertyName = 'password'
grails.plugin.springsecurity.rest.logout.endpointUrl = '/api/logout'
grails.plugin.springsecurity.rest.token.generation.useSecureRandom = true
grails.plugin.springsecurity.rest.token.generation.useUUID = false
grails.plugin.springsecurity.rest.token.storage.useGorm = false
grails.plugin.springsecurity.rest.token.storage.gorm.tokenDomainClassName = null
grails.plugin.springsecurity.rest.token.storage.gorm.tokenValuePropertyName = 'tokenValue'
grails.plugin.springsecurity.rest.token.storage.gorm.usernamePropertyName = 'username'
grails.plugin.springsecurity.rest.token.rendering.usernamePropertyName = 'username'
grails.plugin.springsecurity.rest.token.rendering.authoritiesPropertyName = 'roles'
grails.plugin.springsecurity.rest.token.validation.active = true
grails.plugin.springsecurity.rest.token.validation.headerName = 'X-Auth-Token'
grails.plugin.springsecurity.rest.token.validation.endpointUrl = '/api/validate'
//Exclude normal controllers from basic auth filter. Just the JSON API is included
grails.plugin.springsecurity.filterChain.chainMap = [
'/api/**': 'JOINED_FILTERS,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter', // Stateless chain
'/**': 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter' // Traditional chain
]
I'm not sure what to do next. How can I to call the api? For example, I have Client domain. How to get the list of all clients with the rest api?
Client.groovy
class Client {
Long id
String name
String toString(){
"${name}"
}
static hasMany = [users: User, apps: App]
static constraints = {
name blank: false
}
}
ClientController.groovy
package m15
import static org.springframework.http.HttpStatus.*
import org.springframework.security.access.annotation.Secured
import grails.transaction.Transactional
#Secured(['IS_AUTHENTICATED_REMEMBERED'])
#Transactional(readOnly = true)
class ClientController {
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond Client.list(params), model:[clientInstanceCount: Client.count()]
}
def show(Client clientInstance) {
respond clientInstance
}
def create() {
respond new Client(params)
}
#Transactional
def save(Client clientInstance) {
if (clientInstance == null) {
notFound()
return
}
if (clientInstance.hasErrors()) {
respond clientInstance.errors, view:'create'
return
}
clientInstance.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'client.label', default: 'Client'), clientInstance.id])
redirect clientInstance
}
'*' { respond clientInstance, [status: CREATED] }
}
}
def edit(Client clientInstance) {
respond clientInstance
}
#Transactional
def update(Client clientInstance) {
if (clientInstance == null) {
notFound()
return
}
if (clientInstance.hasErrors()) {
respond clientInstance.errors, view:'edit'
return
}
clientInstance.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message', args: [message(code: 'Client.label', default: 'Client'), clientInstance.id])
redirect clientInstance
}
'*'{ respond clientInstance, [status: OK] }
}
}
#Transactional
def delete(Client clientInstance) {
if (clientInstance == null) {
notFound()
return
}
clientInstance.delete flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.deleted.message', args: [message(code: 'Client.label', default: 'Client'), clientInstance.id])
redirect action:"index", method:"GET"
}
'*'{ render status: NO_CONTENT }
}
}
protected void notFound() {
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'client.label', default: 'Client'), params.id])
redirect action: "index", method: "GET"
}
'*'{ render status: NOT_FOUND }
}
}
}
Are you able to login and get a token?
I am using Grails 3.2.0.M1 and the following settings in application.groovy
I setup a test app and use GORM to store tokens.
I first needed to install the gorm plugin otherwise the tokens would not get stored.
compile "org.grails.plugins:spring-security-rest-gorm:2.0.0.M2"
application.groovy:
grails.plugin.springsecurity.rest.login.active=true
grails.plugin.springsecurity.rest.login.endpointUrl='/api/login'
grails.plugin.springsecurity.rest.login.failureStatusCode=401
grails.plugin.springsecurity.rest.login.useJsonCredentials=true
grails.plugin.springsecurity.rest.login.usernamePropertyName='username'
grails.plugin.springsecurity.rest.login.passwordPropertyName='password'
grails.plugin.springsecurity.rest.logout.endpointUrl='/api/logout'
grails.plugin.springsecurity.rest.token.storage.useGorm=true
grails.plugin.springsecurity.rest.token.storage.gorm.tokenDomainClassName='dashboard.AuthToken'
grails.plugin.springsecurity.rest.token.storage.gorm.tokenValuePropertyName='tokenValue'
grails.plugin.springsecurity.rest.token.storage.gorm.usernamePropertyName='username'
grails.plugin.springsecurity.rest.token.generation.useSecureRandom=true
grails.plugin.springsecurity.rest.token.generation.useUUID=false
grails.plugin.springsecurity.rest.token.validation.active=true
grails.plugin.springsecurity.rest.token.validation.endpointUrl='/api/validate'
grails.plugin.springsecurity.rest.token.storage.jwt.expiration=99999
I used curl to test the login and see if a token was returned:
curl -v -H "Content-Type: application/json" -X POST -d '{"username":"me","password":"password"}' http://localhost:8090/api/login
This returned:
* Hostname was NOT found in DNS cache
* Trying ::1...
* Connected to localhost (::1) port 8090 (#0)
> POST /api/login HTTP/1.1
> User-Agent: curl/7.38.0
> Host: localhost:8090
> Accept: */*
> Content-Type: application/json
> Content-Length: 39
>
* upload completely sent off: 39 out of 39 bytes
< HTTP/1.1 200 OK
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< Cache-Control: no-store
< Pragma: no-cache
< Content-Type: application/json;charset=UTF-8
< Content-Length: 112
< Date: Wed, 01 Jun 2016 09:34:00 GMT
<
* Connection #0 to host localhost left intact
{"username":"me","roles":["ROLE_ADMIN"],"token_type":"Bearer","access_token":"ek6bonq0jnvn40pbgb4qamptorfrdotb"}
The access_token is ek6bonq0jnvn40pbgb4qamptorfrdotb
Secured controller test action:
class TestController {
def index() {
def l = SysRole.list()
render l as JSON
}
}
Then I tested this secured controller using curl and the token which lists the user roles:
curl -v -X POST http://localhost:8090/test -H "Authorization: Bearer ek6bonq0jnvn40pbgb4qamptorfrdotb"
* Connected to localhost (::1) port 8090 (#0)
> POST /test HTTP/1.1
> User-Agent: curl/7.38.0
> Host: localhost:8090
> Accept: */*
> Authorization: Bearer ek6bonq0jnvn40pbgb4qamptorfrdotb
>
< HTTP/1.1 200 OK
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< X-Application-Context: application:development:8090
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 01 Jun 2016 09:39:52 GMT
<
* Connection #0 to host localhost left intact
[{"id":1,"authority":"ROLE_ADMIN"},{"id":2,"authority":"ROLE_USER"}]
Testing with an invalid token gives a 401 unauthorized:
* Connected to localhost (::1) port 8090 (#0)
> POST /test HTTP/1.1
> User-Agent: curl/7.38.0
> Host: localhost:8090
> Accept: */*
> Authorization: Bearer invalid_token
>
< HTTP/1.1 401 Unauthorized
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< WWW-Authenticate: Bearer error="invalid_token"
< Content-Length: 0
< Date: Wed, 01 Jun 2016 09:43:08 GMT
<
* Connection #0 to host localhost left intact

How to get json structure in Rails?

my application should sent structure via json,
that functions works fine:
function send_json()
{
var formData = form2object('myForm');
var json_data = JSON.stringify(formData, null, '\t');
$.post("", json_data);
}
It create json_data and send it via post.
But I don't understand how to catch this data on another side, can you help me ?
I should take this structure and make some actions with it.
when i send data i got json:
{ "type": "test", "ttl": "1", "amount": "1", "rules": { "rule1": "1", "value1": "4444", "stackcount1": "1", "rule2": "2", "value2": "333", "stackcount2": "2" }}
In the contoller i wrote this:
class AdminController < ApplicationController
def index
#json_string = params[:amount]
if !#json_sting.nil?
#json_string = JSON.parse(params[:amount])
end
end
end
in the view(haml) i wrote:
=#json_string
It doesn't work !
But wireshark shows:
POST /admin/ HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:14.0) Gecko/20100101 Firefox/14.0.1
Accept: */*
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://localhost:3000/admin/
Content-Length: 192
Cookie: _GiftSenderTool_session=BAh7BzoQX2NzcmZfdG9rZW4iMTVyNVJCMTBvcGpKSk5OcFN4bW15YVlpRlF1TUNtb1gwZkY0bTRuRHlsNnM9Ig9zZXNzaW9uX2lkIiU4ZjFjNTNjNTY0MTQ1MGExNmFiODcxZGEyYzU5ZTkxMg%3D%3D--f21bf3b96edc3bc551c8de68acc6da17685d58b4
Pragma: no-cache
Cache-Control: no-cache
{
."type": "test",
."ttl": "1",
."amount": "1",
."rules": {
.."rule1": "1",
.."value1": "4444",
.."stackcount1": "1"
.},
."authenticity_token": "n3B6D/Km9zOgOzlosK/OLHyTCDLk3MyCTlTBinfQcnY="
}
It means that i can't get data.
you have to catch your JSON object in some rails controller action. If your JSON string looks like this:
{ "user": { "id": 1, "name": "Tom" } }
then do it like this:
require "json"
...
def some_action
user = JSON.parse(params[:user])
puts "User id is #{user[:id]}"
...
end

Resources