MAX SDK: UI Object with Multiple Textedit fields?
Greetings,
I'd like to create a custom UI object that has multiple text edit fields.
Context: My externals connect to a cloud service to enable access to data from that cloud in Max. In order to connect we need to gather user auth credentials. I don't really want to use Max's standard textedit objects for this. Because distributing patches that pass user's sensitive data trough patch chords seems like a bad idea. I want to build a custom UI object user's can type into so masked data remains at the code level and is never accessible in the patch itself.
Current State: I found the uitextfield example in the Max SDK. I can definitely use this as a starting point. It will be easy to modify this to mask the data onstream, and pass the the user input to other objects using the notification system so it's never exposed in the patcher itself. I could use 2 or more objects based on uitextfield to compose a bpatcher that will serve as my Authentication screen.
Problem: It would be better for the Auth Screen to be a single Max object. The default textfields are fairly nondescript. If I distribute my patcher, a nefarious actor could swap out my custom textfields with some other textfields. The auth screen would look unchanged, but the user has just typed their credentials into an illegitimate input field.
The Question: I'm not seeing a way to include multiple textfields in a single object. In fact, making an object a textfield seems to overwrite most of paint's other functions. Is there a way to compose a UI objects from multiple component UI Objects? Or a different way to get multiple textfields into my object?
I'm aware that instead of using textfields I could paint text directly and repaint based on the key methods. But this results in some behaviour that don't feel natural (like being unable drag over and highlight the text). I would like this auth solution to appear to be as seemless and native as possible.
I know I've posted a number of similar threads on this topic. Thanks to all for your input!
Hi Joe, I can't understand why you think that it would be unsafe to enter the data into a textedit object or, conversely, that it would somehow be safer if it were typed directly into a UI external.
If someone spreads a fake version of your patcher, neither method will provide any security benefit or prevent that keyboard input is logged. Maybe you can read the contents of the textedit objects from the external and then nothing will be sent through patchlines, but can you explain where you see risks and why they are supposedly eliminated by direct input into the external?
Hi! Thanks for your reply. To be honest, I thought I had closed the window without actually posting this message. After some exploration of how textedit works in MaxSDK, it's pretty clear that there can only be one textedit field per object. All the textedit functions take a pointer to the object. I could theoretically generate another t_object and designate it as a textedit object. But there's no way to render the second textedit that I can see. One textfield per Max object. It seems reasonable. If we want to compose forms of multiple textfields, that's exactly what the patcher layer is for. So I've made peace with this.
To your question:
I know there's no absolute guarantee of security. And if a bad actor really wants to find a way to do something bad they will. But I do want to at least remove the most obvious angles of approach. I also want the UX to seem as native as possible, and look and feel just like any other online service login.
If I use the stock [textedit] object and pass someone's password through a patchline to my external, there are two problems:
1) Masking a password in stock [textedit] ((i.e replacing it with *** as you type) is definitely not supported out of the box. Perhaps something like this could be achieved with a bunch of subpatching, by sending "set" messages after every keystroke... and then appending the next keystroke to a value stored in a hidden message box or something. I didn't look too deeply into this. Just thinking about it raises a whole bunch of questions that immediately make me think this is the kind of problem best solved in code, not with Max patching.
2) Even if I could mask the value in the display, sending the password through a patchchord to my external makes it just WAY to easy to intercept. A fake version of my patch could add two or three new objects, and immediately get access to the user's password in plain text. The real kicker here is that they can do this without interrupting the proper functioning of the patch. The tampered auth flow will still auth successfully.
If someone's going to troll me or my users, I'd like them to at least make them work for it. I believe requiring them to actually try will immediately discourage most of the of bad actors out there.
Using a custom textedit object solves both these problems. (1) In a few lines of code we can store the string that is typed but display a series of asterisks. (2) And I can use the SDK's notify method to send the data to my other objects so the it never passes through the patcher layer.
The main benefit here is that the text fields are now tightly coupled to the rest of my solution. A bad actor could tamper with the patch, but if they ask the user to enter their information in any way other than the exact method I've prescribed the process will fail.
Someone could create a patch with an auth screen that looks exactly like mine but uses regular [textedit] objects instead of my custom objects. They can steal the user's password, but the user will immediately know something is up because they won't actually be able to connect. So the user deletes the patch, reports it, and refreshes their password through a proper channel. This feels much safer to me.
The bonus solution would have been to render the entire auth method (including all necessary textfields) as a single Max object. This would require a lot more investment to create a counterfeit. But it doesn't look like that's actually possible with Max. Which is fine. The SDK does not have to allow you to build something that would actually be easier to build in Max itself.
So I'll have a slick looking bpatcher to handle the login. The worst someone can do is copy it and distribute a broken version that doesn't work.
Thanks again for all your help with this. I think this recent flurry of posts turned out to be unnecessary once I remembered all the solutions to all the previous problems. I do wish there was better documentation of how MinDevkit and Max SDK play together. There are quite a few hidden gotchas. But once you've found them the end result seems to be quite nice!
I never heard of a case where "bad actors" did something like that in the Max world. Tell the users they must get the software from your official source only or they take a risk of getting fake stuff. I don't think you even need to communicate this because it applies to all software and is self-evident.
You can also put something into an external that validates the patcher that contains it. A checksum or something similar. Instead of typing into a UI object you could also bring up a dialog or a scripted patcher that doesn't exist as file. Even the authorization screen of Max is a (locked down) patcher with a jweb object probably.
But I don't want to convince you of anything here, I just think that you're wasting time for a result that ultimately doesn't bring security to anyone. If the software becomes popular and has a growing number of users, you can always adjust the login process. Before that happens, it's not interesting to "bad actors" either.