Using Rack::Attack to throttle Basic Auth - basic-authentication

I have gem rack-attack setup for my app. I want to start throttling basic auth authentication based on IP.
My basic auth code setup like so:
# config/environments/production.rb
config.middleware.insert_after(::Rack::Lock, '::Rack::Auth::Basic', ENV['RAILS_ENV') do |u, p|
[u, p] == [ENV['BASIC_AUTH_USERNAME'], ENV['BASIC_AUTH_PASSWORD']]
end
I'd imagine my rack attack would contain something like this:
# config/initializers/rack_attack.rb
Rack::Attack.throttle('req/ip', limit: 2, period: 60.seconds) do |req| req.ip
# what should belong here???
end

Please see my github comment about this question.

Related

How to Connect Salesforce using R?

I am getting 500 status. Can you anyone help me on this please
I am trying to connect Salesforce using R when i try perform the login operation. I am not successful, can you please look into this code and correct me where i am missing.
library(RCurl)
library(httr)
body1 = '<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<login xmlns="urn:partner.soap.sforce.com">
<username>xxxxxx.Test#xxxxxx.com.xxxxxxx</username>
<password>xxxxxxxxxxxx</password>
</login>
</s:Body>
</s:Envelope>'
x <- httr::POST(url = "https://test.salesforce.com/services/Soap/48.0", body = body1, content_type("text/xml;charset=UTF-8"),SOAPAction = "login")
x$status_code
Thanks for answering the questions. After several tries, I understood there was some issue in the headers. I fixed the headers and its now working great. I am able to perform a query in Salesforce without any issues. I have posted my complete code here so anyone can make use for it. I am not an expert in this but still managed with this code.
#######Required Packages
library(RCurl)
library(httr)
library(XML)
library(jsonlite)
library(xml2)
library(magrittr)
library(randomNames)
library(rlang)
library(generator)
library(stringr)
require(data.table)
body1 = '<?xml version="1.0" encoding="utf-8"?>\
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">\
<s:Body>\
<login xmlns="urn:partner.soap.sforce.com">\
<username>XXXXXXXXXXXXXX</username>\
<password>XXXXXXXXXXXXXXX</password>\
</login>\
</s:Body>\
</s:Envelope>\n'
require(httr)
################################Posting the Login##############################################
result <- POST("https://test.salesforce.com/services/Soap/u/48.0",body = body1,add_headers(.headers = c("Content-Type"="text/xml",'SOAPAction' = "https://test.salesforce.com")))
##############Parsing XML###############################################################
Output <- content(result)
doc = xmlTreeParse(Output, useInternal = TRUE)
top = xmlRoot(doc)
xmlName(top)
names(top)
names(top[[1]] [[1]] [[1]])
Session = top[[ 1 ]] [[1]] [[1]] [["sessionId"]]
SessionId <- Session [1][1]$text
tok <- xmlToList(SessionId)
Se <- paste("Bearer",tok,Sep="")
Se = trimws(Se)
Sever = top[[ 1 ]] [[1]] [[1]] [["serverUrl"]]
SessionURL <- Sever [1][1]$text
################SF Query###########################################
SFQuery <- "SELECT Id,FirstName FROM Conatct limit 10"
SFQuery_Req <- GET(Pam,query = list(q=SFQuery),add_headers(Authorization=Se))
SFQuery_Con <- content(SFQuery_Req, as = 'text') %>% fromJSON()
SFQuery_Con_DF <- data.frame(SFQuery_Con$records)
It can be many things, not all related to your code...
Your SOAP namespaces might be wrong. Maybe try with SoapUI / Postman / curl first and once you get these to work - check the code. Try with this version of the tags
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:partner.soap.sforce.com">
<soapenv:Body>
<urn:login>
<urn:username>usernamegoeshere</urn:username>
<urn:password>passwordgoeshere</urn:password>
</urn:login>
</soapenv:Body>
</soapenv:Envelope>
Log in to the SF org manually and check that user's login history at bottom of the page. Do you see your attempt at all? If not - are you sure you're connecting to right place (production vs sandbox)? Or maybe you have some proxy installed by your corporate IT and it just swallows the connections... If there's an entry in the login history - does it say invalid password? Too many failed login attempts? Security token needed?
It's possible admin disabled logging in from generic test.salesforce.com and you'll have to use what you see in Setup -> My Domain.
It's possible admin set your user for Single Sign-On (do you see normal SF login page or are redirected to some Active Directory stuff for example). If that's the case it'll be trickier to connect via API.
Maybe your user is not API-enabled, that'd be a Profile / Permission Set thing. Do you use system administrator account? Are there any login policies on the profile like access only from certain IPs or during certain login hours.
I maintain an R package called {salesforcer} that allows users to interact with 6 different Salesforce APIs (SOAP, REST, Bulk 1.0, Bulk 2.0, Metadata, Reports and Dashboards) to manage their Orgs. If one of these APIs suite your needs I would recommend using the package so that you do not need to write the code from scratch. Below is an example for how to connect using either OAuth 2.0, sometimes referred to as Single Sign-On, or with a username, password, and security token. Please visit the package's documentation site for additional detail and vignettes at: https://stevenmmortimer.github.io/salesforcer/
# install.packages('salesforcer')
library(salesforcer)
# Using OAuth 2.0 authentication
sf_auth()
# Using Basic Username-Password authentication
sf_auth(username = "test#gmail.com",
password = "{PASSWORD_HERE}",
security_token = "{SECURITY_TOKEN_HERE}")
# pull down information of person logged in
# it's a simple API call to get started
# and confirm connection to the APIs
user_info <- sf_user_info()
sprintf("Organization Id: %s", user_info$organizationId)
#> [1] "Organization Id: 00D6A0000003dN3UAI"
sprintf("User Id: %s", user_info$userId)
#> [1] "User Id: 0056A000000MPRjQAO"

Migrating drupal users to firebase auth

I am attempting to migrate users from Drupal 8 into firebase auth.
I have tried following the instructions on https://firebase.google.com/docs/auth/admin/import-users#import_users_with_md5_sha_and_pbkdf_hashed_passwords.
The users import successfully, but the password does not work when I attempt to log in. After reversing the Drupal code, I'm getting the feeling that the sha512 hashing mechanism provided by firebase is not doing the same steps as what drupal does to determine the hash of the password.
The data in the drupal database for one user (this is dev data, not real user)
password: $S$EF//ORKHHZKG9L4UEUUNycm0v5HatfjQxkxbKn19BiYMsPxi3u68
From reading through the drupal code, I've determined the following
$S$ = SHA512
"E" = 16 rounds
"F//ORKH" = the salt
"HZKG9L4UEUUNycm0v5HatfjQxkxbKn19BiYMsPxi3u68" = the hash
This was taken from here: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Password%21PhpassHashedPassword.php/class/PhpassHashedPassword/8.7.x
The relevant Go code for the import:
users := []*auth.UserToImport{
(&auth.UserToImport{}).
UID("00048ebbb178d47f674f48485205235c").
Email("CPIZFTPX#mailinator.com").
PasswordHash([]byte("HZKG9L4UEUUNycm0v5HatfjQxkxbKn19BiYMsPxi3u68")).
PasswordSalt([]byte("F//ORKH")),
}
h := hash.SHA512{
Rounds: 16,
}
result, err := client.ImportUsers(context.Background(), users, auth.WithHash(h))
So... with all of that said, i think the issue is that the drupal code is truncating the string that is actually being stored in the database to 55 characters. You can see this in the last line of the crypt method in the drupal code (url pasted above).
Has anyone out there successfully migrated drupal 8 users to firebase? If so, I'd love to know what step im missing. If not, some confirmation of my findings would help with my sanity.
From looking at this, It doesn't look like that is a SHA. Most systems encode the Bytes of the SHA into a string for ease of storage. Looking at the Drupal code file you posted, it looks like they base64 encode the SHA.
In this case, I believe it needs to be decoded before being passed into PasswordHash
Try adding:
decoded, err := base64.StdEncoding.DecodeString("HZKG9L4UEUUNycm0v5HatfjQxkxbKn19BiYMsPxi3u68")
Then just pass it into the rest of your code:
users := []*auth.UserToImport{
(&auth.UserToImport{}).
UID("00048ebbb178d47f674f48485205235c").
Email("CPIZFTPX#mailinator.com").
PasswordHash(decoded).
PasswordSalt([]byte("F//ORKH")),
}
h := hash.SHA512{
Rounds: 16,
}
result, err := client.ImportUsers(context.Background(), users, auth.WithHash(h))
I don't know what the password is, or I would have tested it out on my firebase account.

Adding a button for google signin using f#/fable/asp.net/react

I'm working with the SAFE stack (https://safe-stack.github.io/) and through the example dojo. It's great so far.
I'd like to extend the example to include a button to login/auth via Google. So I looked at an example on the Google website (https://developers.google.com/identity/sign-in/web/build-button). And then I had a look how to do authentication using ASP.NET (https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/google-logins?view=aspnetcore-2.1&tabs=aspnetcore2x) As a result I ended up confused as to how to integrate this into a SAFE project. Can someone tell me what they would do? SHould I be trying to use ASP.NET Identity or should I be using the JWT approach? I don't even know if they are the same since I'm very new to web frameworks.....
The other question I have is how would one inject raw Javascript into the client side of a SAFE project. The google example above shows raw JS/CSS/HTML code? Should I be injecting that as is or should I look in React for some button that does this and map that idea back through Fable?
Setting up OAuth
The easiest way to use Google OAuth is to wait until the next release of Saturn, at which point Saturn will include the use_google_oauth feature that I just added. :-) See the source code if you're interested in how it works, though I'm afraid you can't implement this yourself with use_custom_oauth because you'll run into a type error (the underlying ASP.NET code has a GoogleOptions class, and use_custom_oauth wants an OAuthOptions class, and they aren't compatible).
To use it, add the following to your application CE:
use_google_oauth googleClientId googleClientSecret "/oauth_callback_google" []
The last parameter should be a sequence of string * string pairs that represent keys and values: you could use a list of tuples, or a Map passed through Map.toSeq, or whatever. The keys of that sequence are keys in the JSON structure that Google returns for the "get more details about this person" API call, and the values are the claim types that those keys should be mapped to in ASP.NET's claims system. The default mapping that use_google_oauth already does is:
id → ClaimTypes.NameIdentifier
displayName → ClaimTypes.Name
emails[] (see note) → ClaimTypes.Email
Those three are automatically mapped by ASP.NET. I added a fourth mapping:
avatar.url → `"urn:google:avatar:url"
There's no standard ClaimTypes name for this one, so I picked an arbitrary URN. Caution: this feature hasn't been released yet, and it's possible (though unlikely) that this string might change between now and when the feature is released in the next version of Saturn.
With those four claim types mapped automatically, I found that I didn't need to specify any additional claims, so I left the final parameter to use_google_oauth as an empty list in my demo app. But if you want more (say you want to get the user's preferred language to use in your localization) then just add them to that list, e.g.:
use_google_oauth googleClientId googleClientSecret "/oauth_callback_google" ["language", "urn:google:language"]
And then once someone has logged in, look in the User.Claims seq for a claim of type "urn:google:language".
Note re: the emails[] list in the JSON: I haven't tested this with a Google account that has multiple emails, so I don't know how ASP.NET picks an email to put in the ClaimTypes.Email claim. It might just pick the first email in the list, or it might pick the one with a type of account; I just don't know. Some experimentation might be needed.
Also note that third-party OAuth, including GitHub and Google, has been split into a new Saturn.Extensions.Authorization package. It will be released on NuGet at the same time that Saturn's next version (probably 0.7.0) is released.
Making the button
Once you have the use_google_oauth call in your application, create something like the following:
let googleUserIdForRmunn = "106310971773596475579"
let matchUpUsers : HttpHandler = fun next ctx ->
// A real implementation would match up user identities with something stored in a database, not hardcoded in Users.fs like this example
let isRmunn =
ctx.User.Claims |> Seq.exists (fun claim ->
claim.Issuer = "Google" && claim.Type = ClaimTypes.NameIdentifier && claim.Value = googleUserIdForRmunn)
if isRmunn then
printfn "User rmunn is an admin of this demo app, adding admin role to user claims"
ctx.User.AddIdentity(new ClaimsIdentity([Claim(ClaimTypes.Role, "Admin", ClaimValueTypes.String, "MyApplication")]))
next ctx
let loggedIn = pipeline {
requires_authentication (Giraffe.Auth.challenge "Google")
plug matchUpUsers
}
let isAdmin = pipeline {
plug loggedIn
requires_role "Admin" (RequestErrors.forbidden (text "Must be admin"))
}
And now in your scope (NOTE: "scope" will probably be renamed to "router" in Saturn 0.7.0), do something like this:
let loggedInView = scope {
pipe_through loggedIn
get "/" (htmlView Index.layout)
get "/index.html" (redirectTo false "/")
get "/default.html" (redirectTo false "/")
get "/admin" (isAdmin >=> htmlView AdminPage.layout)
}
And finally, let your main router have a URL that passes things to the loggedInView router:
let browserRouter = scope {
not_found_handler (htmlView NotFound.layout) //Use the default 404 webpage
pipe_through browser //Use the default browser pipeline
forward "" defaultView //Use the default view
forward "/members-only" loggedInView
}
Then your login button can just go to the /members-only route and you'll be fine.
Note that if you want multiple OAuth buttons (Google, GitHub, Facebook, etc) you'll probably need to tweak that a bit, but this answer is long enough already. When you get to the point of wanting multiple OAuth buttons, go ahead and ask another question.

Alexa Echo Dot - ASK skill problems

I'm tying to make a simple test custom Alexa Skill, but I'm stuck and I'm not sure what the problem is. Maybe someone more experienced know what I'm missing?
Invocation Name
home system
Intent Schema
{
"intents": [
{
"intent": "AMAZON.HelpIntent",
"slots": []
},
{
"intent": "TestIntent",
"slots": [
{"name": "test", "type": "AMAZON.NUMBER"}
]
}
]
}
Sample Utterances
TestIntent set state {test}
TestIntent add state
I have written my own little python server on my own self hosted server, I already have a working news flash skill on the same system. I have spend plenty of time looking at the documentation, reading tutorials and I looks like I have done what I'm supposed to do.
The result I get is this:
A LaunchRequest works, both in the Service Simulator and on the Echo. It triggers a HTTP POST with the expected JSON, and I get the expected voice reply.
But the IntentRequest only works from the Service Simulator, it never works on the Echo. I say for example "alexa home system set state eight", no requests are made to my server, the echo just makes a sound and that's all.
I have no idea how to debug this, the skill is a US skill and my Echo is in US mode. I have tried to set the endpoint in both Europe and North America. Tried different trigger words, different slots, no slots ... and I have of course checked under Settings -> History to make sure that the device understood me correctly.
Any idea what to try next? How to debug this?
I found the problem, it was a classic PEBCAK (Problem Exists Between Chair And Keyboard) problem.
I had missed that I had to be much more precise how to invoke an intent (a single sentence that contains both the trigger word and intent in one go). A example of valid and working examples are:
Alexa, ask home system to set state nine
Alexa, set state twelve using home system
Alexa, tell home system set state one
I realised this when I used the alternative 2-step invoking, and realized that it worked. It had to be the way I invoked the skill, not the backend:
Alexa, open home system
(Alexa responds, and listens for the command)
Set state to eight
(Intent triggered, Alexa responds)
The first request above is the LaunchRequest
The LaunchRequest responds with shouldEndSession: false, if not the session will end. That's maps to question(...) in my code.
There are plenty of more ways to trigger the skills, a full list see this page: https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/supported-phrases-to-begin-a-conversation (scroll down to the tables)
Finally thank you u-gen for the feedback, bst was a interesting project (never tried it), guess it can be really useful if you uses a hosted solution like lambda. But thanks to the docs I found flask-ask, a project that simplified my code.
Finally, the python part of my test project if someone else like to try it out.
#!/usr/bin/env python
from flask import Flask, render_template
from flask_ask import Ask
from flask_ask import statement, question, convert_errors
app = Flask(__name__)
ask = Ask(app, '/ask/')
#app.route('/')
def hello_world():
return 'Hello, World!'
#ask.launch
def launched():
return question('Welcome to Foo')
#ask.intent('TestIntent')
def hello():
return statement('Hello, world')
#ask.session_ended
def session_ended():
return "", 200
if __name__ == '__main__':
app.run(debug=True, host="0.0.0.0", threaded=True)

Drupal Block user from login for X days

Is there any module which block/truncate the user from login for X(say 5) days.
It should shows notification "You have been blocked for 5 days by moderator" or something like that.
Thanks,
Edvin
On what condition you want block him?
Here's module for blocking: ban_unpublish and i assume there's more modules for that.
But i prefer Rules, where you can set rules on conditions to block users...

Resources