Okay, I needed to define a custom login method because the server holding the accounts, while not being under my control, is a fully trusted source, so something like OAuth is a) not possible and b) not needed.
I want to stress that this whole thing works just fine in the browser.
Here’s the relevant portion of my React class:
import React from 'react';
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button';
import { Accounts } from 'meteor/accounts-base';
import Typography from '@material-ui/core/Typography';
import Tappable from 'react-tappable/lib/Tappable';
class Login extends React.Component {
state = {
user: '',
password: '',
error: ''
}
onUserChange = (e) => {
this.setState({
user: e.target.value
})
}
onPasswordChange = (e) => {
this.setState({
password: e.target.value
})
}
loginUserWithNextCloud = (user,password,callback) => {
const loginRequest = {
custom: true,
user: user,
password: password
}
console.log("Beginning client login, about to call method from within");
Accounts.callLoginMethod({
methodArguments: [loginRequest],
userCallback: callback
});
}
tryLogin = () => {
//TODO: Set spinner while waiting for response
this.setState({
error: ""
});
this.loginUserWithNextCloud(this.state.user, this.state.password, (err,res) => {
if(err) {
this.setState({
error: "Username / Passwort falsch!"
});
} else {
this.props.history.push("/");
}
})
}
render() {
return(
<div>
<TextField value={this.state.user} placeholder="Username" onChange={this.onUserChange} /><br />
<TextField value={this.state.password} type="password" onChange={this.onPasswordChange} /><br />
{!this.state.error && <Typography>{this.state.error}</Typography>}
<Tappable onTap={this.tryLogin}>
<Button onClick={this.tryLogin}>Absenden</Button>
</Tappable>
</div>
)
}
}
export default Login;
and here’s how the method is currently setup on the server:
Accounts.registerLoginHandler("custom", (loginRequest) => {
if(!loginRequest.custom) return undefined;
let code = 0;
let result = '';
try {
console.log("Trying to log in");
result = HTTP.call("GET", "https://foo.bar.baz/ocs/v1.php/cloud/users/" + loginRequest.user,
{
auth: loginRequest.user+":"+loginRequest.password,
headers: {
"OCS-APIRequest": true
}
}
)
code = result.statusCode;
} catch(err) {
//code = err.response.statusCode;
console.log("error with call");
}
if(code == 200) {
//wrangle the resulting data
const serviceName = "nextcloud";
const serviceData = {
id: "foo",
fullname: "bar",
group: "baz"
}
return Accounts.updateOrCreateUserFromExternalService(
serviceName,
serviceData
)
} else {
console.log("Wrong login attempt");
}
})
This works great in the browser. On Cordova and Android… not so much. I’m seeing the console.log before the call to the Accounts method. But I never see the corresponding logs from the server, nevermind being logged in or anything.
Also hotpush seems to be broken completely - every time I change code for the client, it simply does not turn up, which means I have to stop the server completely and restart the build process.
Will have a look at what iOS says next.