Multi-step MFA with custom ADFS 3.0 IAuthenticationAdapter - authentication

I'm setting up custom MFA providers for ADFS 3.0 by implementing IAuthenticationAdapter, I want to add another step in to the authentication process whereby, for example with email-based OTP, the user is first prompted to confirm his or her email address before the code is sent and then the user is prompted to enter the OTP, or perhaps the user is prompted to verify some mobile digits before sending out an SMS OTP, however the workflow in the authentication pipeline seems quite rigid, you get BeginAuthentication, OnError and TryEndAuthentication, but implementing additional steps seems much more involved.
So far I have some up with two possible solutions, and I'd like to hear if anyone as any comments or preferences, or hopefully a better way of doing this.
Call TryEndAuthentication more than once, passing a different context to represent which stage of the process should be rendered with an IAdaperPresentation.
Add jQuery and other custom scripts as text resources to the custom provider assembly and then inject them in to the IAdapterPresentationForm.GetFormHtml method to make the form dynamic and even do some in-line AJAX calls to a separate MVC / Web API service, and do the email verification before showing the user the authentication form, such that you end up with something like this...
Here's my custom script resource (Provider.txt):
function alertMe() {
$("#serviceResponse").html("It Works!");
}
And here's what I did in GetFormHtml:
var jQuery2 = Properties.Resources.jQuery2;
var script = Properties.Resources.Provider;
result += "<script type=\"text/javascript\">";
result += jQuery2;
result += "</script>";
result += "<form method=\"post\" id=\"loginForm\" autocomplete=\"off\">";
...
result += " <input id=\"alertButton\" type=\"button\" name=\"Alert\" value=\"Alert Me\" onclick=\"alertMe();\" />";
result += " <div id=\"serviceResponse\" />";
...
result += " <input id=\"continueButton\" type=\"submit\" name=\"Continue\" value=\"Continue\" />";
result += "</form>";
result += "<script type=\"text/javascript\">";
result += script;
result += "</script>";
I've not tried the first method yet, and I'm not even sure if the ADFS authentication pipeline will allow this kind of workflow.
I have tried the second method and amazingly it does work, although, as I'm sure you'll agree that from a Developer's point-of-view it's nowhere near as clean as I'd like!
So what do you think, am I missing a simple setting or interface which I could cleanly implement to do this, or is this the only way?

Related

How to pass UserName & Password in IBMMQ Client Message using .NET or C++ Program

I am writing a .NET Console application, our goal is keep a message on the queue and read the message. the message header should contain User Name & Password. I try to pass the Message with below code it is not working.
hashTable.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_CLIENT);
hashTable.Add(MQC.HOST_NAME_PROPERTY, strServerName);
hashTable.Add(MQC.CHANNEL_PROPERTY, strChannelName);
hashTable.Add(MQC.PORT_PROPERTY, 1414);
hashTable.Add(MQC.USER_ID_PROPERTY, "XXXXXX");
hashTable.Add(MQC.PASSWORD_PROPERTY, "XXXXXX");
hashTable.Add(MQC.USE_MQCSP_AUTHENTICATION_PROPERTY, true);
queueManager = new MQQueueManager(strQueueManagerName,hashTable);
queue = queueManager.AccessQueue(requestQueue, MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING);
requestMessage = new MQMessage();
requestMessage.WriteString(StrAPICMessage);
requestMessage.Format = MQC.MQFMT_STRING;
requestMessage.MessageType = MQC.MQMT_REQUEST;
requestMessage.Report = MQC.MQRO_COPY_MSG_ID_TO_CORREL_ID;
requestMessage.ReplyToQueueName = responseQueue;
requestMessage.ReplyToQueueManagerName = strQueueManagerName;
queuePutMessageOptions = new MQPutMessageOptions();
queue.Put(requestMessage, queuePutMessageOptions);
In the Message Descriptor it is taking the default value mentioned MQ Server. it is not takeing my UserName "XXXXX"
I have tried using the CSICS Bridge header also unable to send the message with my application Service account + Password.
help me on this scenario.
See "MQCSP authentication mode" here: https://www.ibm.com/docs/en/ibm-mq/latest?topic=authentication-connection-java-client
It says:
In this mode, the client-side user ID is sent as well as the user ID and password to be authenticated, so you are able to use ADOPTCTX(NO). The user ID and password are available to a server-connection security exit in the MQCSP structure that is provided in the MQCXP structure.
"client-side user ID" means the UserId that the application is running under. Therefore, if you are authenticating with a different UserId than the one that the application is running under.
Therefore, you (or your MQAdmin) will need to change ADOPTCTX to YES.
Your program works fine for me, when I fill in the correct values for my qmgr connection.
Except for one change I made: instead of TRANSPORT_MQSERIES_CLIENT I used TRANSPORT_MQSERIES_MANAGED. That keeps everything in the managed .Net space.
Without that change, I was actually getting MQRC_UNSUPPORTED_FUNCTION during the connection which typically means either some kind of mismatch between versions of interfaces, or it couldn't find the C dll that underpins the unmanaged environment. And I wasn't going to take time to dig into that further.
Running amqsbcg against the output queue, I see
UserIdentifier : 'mqguest '
which is the id I had set in the USER_ID_PROPERTY.

Changing Postman request name from prerequest script

I'm currently trying to implement few Postman requests with CSV data sources.
For instance let assume I have request named "Open as user".
In csv file, I have bunch of user credentials with description field that describes user role.
I would like to have the ability to change request names to reflect each user roles.
For instance, if the request is made as the admin user I would like request name in reports and runner to be "Open as user admin".
In documentation, I've found pm.info.requestName variable but seems it is read-only.
I put following in Pre-request Script
pm.info.requestName = "1";
console.log(pm.info.requestName);
but got "Open as user" value instead of assigned "1".
Have anyone tried to do the same trick or know whether it is possible at all?
I was looking for a solution to this as well and i have solved it in the following way:
Use the 'Pre-request Script' to determine what role the user has.
Set the url to a environment- or global-variable
Use that url in the request, like {{url}}
Clear the environment- or global-variable in the 'Tests' tab
In my case i used the environment variable to get the environment, instead of you, using the data variables.
var environment = pm.environment.get("environment");
var url;
switch(environment) {
case "test":
url = pm.globals.get("test-url");
break;
case "acc":
url = pm.globals.get("acc-url");
break;
case "prod":
url = pm.globals.get("prod-url");
break;
default:
url = pm.globals.get("test-url");
break;
}
pm.environment.set("url", url);
Hope this helps!
I'm afraid that you can't do that. pm.request object is available only after request execution. I even think that you can't access the request name the way you want (I though I would find it in the 'id' member, but it was empty)
Have a look here to see what's available in terms of members and methods concerning the request object.
You may find another way of proceeding (maybe duplicate your test, rename it with admin and, under proper condition, launch the admin request instead of the common user request ? it's kind of a hassle just for a test name)
I think about something else: you could just customize your assertions label, that's what I do to have 'readable' test names in TFS reports. In the Tests tab :
test_name = "[ "+ request.name + " ] - ";
and for each assertion (example):
tests[test_name + "Status code is 200"] = responseCode.code === 200;
This gives, in the response Tests tab, something like :
PASS [Get all configuration]-Status code is 200
Under a particular condition, you can replace request.name with a custom string or do request.name + "admin" ...
hope this helps

twitter stream API track all tweet posted by user who registered in twitter application

I am creating the application which need to track all tweets from user who registered to my application, i tried to track those with streaming API , there are public API, user API , and site API,
in those API it just have an option to follow the user ID by add the comma separated user ID
https://dev.twitter.com/streaming/overview/request-parameters#follow
but i think it is not flexible, if there are a new user registered , i need to rebuild the HTTP request , and also if there are so many users try to listen this stream and query will be so long,
it will be
https://stream.twitter.com/1.1/statuses/filter.json?follow=[user1],[user2],[user3]........[userN],
i afraid the query wont fit, i just need a parameter to filter all user who registered in my application such as, for example.
https://stream.twitter.com/1.1/statuses/filter.json?application=[applicationID]
but i think twitter dev does not provide it
so, is there any way to filter stream by application ID?
I didn't see anything like tracking by application id. If your query become too complex (too many follows/keywords), public streaming api will reject it,
and you can't open more than 2 connections with user stream. So, last solution is using Site Stream, -> you can open as many user connections as you have users registered to your app.
BUT the docs says :
"Site Streams is currently in a closed beta. Applications are no
longer being accepted."
Contact twitter to be sure
Arstechnica has a very interesting article about it. Take a look at this code and the link in the end of this post
If you are using python pycurl will do the job. Its provides a way to execute a function for every little piece of data received.
import pycurl, json
STREAM_URL = "http://chirpstream.twitter.com/2b/user.json"
USER = "YOUR_USERNAME"
PASS = "XXXXXXXXX"
userlist = ['user1',...,'userN']
def on_receive(self, data):
self.buffer += data
if data.endswith("rn") and self.buffer.strip():
content = json.loads(self.buffer)
self.buffer = ""
if "text" in content and content['user'] in userlist:
#do stuff
conn = pycurl.Curl()
conn.setopt(pycurl.USERPWD, "%s:%s" % (USER, PASS))
conn.setopt(pycurl.URL, STREAM_URL)
conn.setopt(pycurl.WRITEFUNCTION, on_receive)
conn.perform()
You can find more information here Real time twitter stream api

equivalent to global "before_filter" in Yesod

I have been attempting to play with Yesod, and I have run into a very simple problem that I can not seem to find a solution to.
Say I want to have a global function, that runs on every request irrelevantly of route or handler (for example an authentication function). Say I want something like
uid <- requireAuthId
to run before every handler function and return control to the handler function when a uid is provided / if it already exists
Where would I slot this in? What is the 'Yesod Way' of doing before filters?
One way to do this is to modify your Yesod instance for your foundation type. Assuming your foundation type is called App, you can do the following to force authorization before any other handlers are called.
instance Yesod App where --the following lines are somewhere within this block.
isAuthorized (AuthR LoginR) _ = return Authorized -- You don't want to accidentally lose access to the login page!
isAuthorized _ _ = do
mauth <- maybeAuth
case mauth of
Just _ -> return Authorized
Nothing -> return $ Unauthorized "You must login first."
Obviously, edit this to suit your needs, but it should give you an idea of how to do this.

Testing WCF with SoapUI

I need your help on one practical issue. I have created a WCF service with basic binding with two operation contact.
1- void StartRegistration - Anonymous member can fill the basic registration form and press submit. All the information will be stored into the database and one link with some random token will be send to user's email address.
2 - void CompleteRegistration - This method validates the token sent into the email address and if token is valid, user account will be activated.
Now I have issue here. Using SoapUI I can call StartRegistration method. Email is sent to destination but I want to pass the token to CompleteRegistration method.
Since it is a WCF service so can not do dependency injection to pass the SoapUI tests :).
Please help.
If I understand your question correctly, you have two WCF methods, one for creating a token and another for confirming it.
What I would do in this case is have the first method, StartRegistration, return the token. Then you could use that token to pass into the CompleteRegistration method quite easily in Soap UI.
Another, quite messy solution, would be to have a groovy script test step in Soap UI that actually connected to the mail account, read the link and parsed the contents.
Edited:
Here is part of the script you'll need. Place it in a groovy step, that will then return the token from your mail.
Note: This code assumes that mail is plain text, not multipart. It also assumes that the mail box only has a single mail. The API for JavaMail is pretty extensive, so if you want to do any magic with it, Google is your friend :) At least, this is somewhere to start.
import javax.mail.*;
import javax.mail.internet.*;
// setup connection
Properties props = new Properties();
def host = "pop3.live.com";
def username = "mymailadress#live.com";
def password = "myPassword";
def provider = "pop3s";
// Connect to the POP3 server
Session session = Session.getDefaultInstance props, null
Store store = session.getStore provider
Folder inbox = null
String content
try
{
store.connect host, username, password
// Open the folder
inbox = store.getFolder 'INBOX'
if (!inbox) {
println 'No INBOX'
System.exit 1
}
inbox.open(Folder.READ_ONLY)
Message[] messages = inbox.getMessages()
content = messages[0].getContent()
//Do some parsing of the content here, to find your token.
//Place the result in content
}
finally
{
inbox.close false
store.close()
}
return content; //return the parsed token