Created
October 9, 2025 20:51
-
-
Save ClementRoyer/d8eeaf8f05253f7618db3b49a8594af3 to your computer and use it in GitHub Desktop.
POC MPG sign-in with Ligue1 OAuth
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const axios = require('axios'); | |
| const crypto = require('crypto'); | |
| async function authenticateMPG(email, password) { | |
| const amplitudeId = crypto.randomUUID(); | |
| const validate = (status) => status < 400; | |
| // Step 1: Initiate auth with MPG | |
| const formData = new URLSearchParams({ email, password }); | |
| const auth = await axios.post( | |
| `https://mpg.football/auth?_data=routes%2F__home%2F__auth%2Fauth&ext-amplitudeId=${amplitudeId}`, | |
| formData.toString(), | |
| { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, maxRedirects: 0, validateStatus: validate } | |
| ); | |
| // Step 2: Follow redirect to Ligue1 OAuth | |
| let redirectUrl = auth.headers['x-remix-redirect'].replace('ext-amplitudeId=', `ext-amplitudeId=${amplitudeId}`); | |
| const oauth = await axios.get(redirectUrl, { maxRedirects: 0, validateStatus: validate }); | |
| // Step 3: Submit credentials to Ligue1 login | |
| const loginUrl = `https://connect.ligue1.fr${oauth.headers.location}`; | |
| const state = loginUrl.match(/state=([^&]+)/)[1]; | |
| const cookies = oauth.headers['set-cookie'].map(c => c.split(';')[0]).join('; '); | |
| const loginData = new URLSearchParams({ state, username: email, password }); | |
| const login = await axios.post(loginUrl, loginData.toString(), { | |
| headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Cookie': cookies }, | |
| maxRedirects: 0, | |
| validateStatus: validate | |
| }); | |
| // Step 4: Get authorization code | |
| const resumeUrl = `https://connect.ligue1.fr${login.headers.location}`; | |
| const resumeCookies = login.headers['set-cookie'].map(c => c.split(';')[0]).join('; '); | |
| const resume = await axios.get(resumeUrl, { headers: { 'Cookie': resumeCookies } }); | |
| // Step 5: Exchange code for session | |
| const code = resume.data.match(/name="code"\s+value="([^"]+)"/)[1]; | |
| const callback = await axios.post('https://mpg.football/auth/callback', `code=${code}`, { | |
| headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, | |
| maxRedirects: 0, | |
| validateStatus: validate | |
| }); | |
| // Step 6: Extract token from dashboard | |
| const sessionCookie = callback.headers['set-cookie'].find(c => c.startsWith('__session=')); | |
| const session = sessionCookie.split(';')[0].split('=')[1]; | |
| const dashboard = await axios.get('https://mpg.football/dashboard?_data=root', { | |
| headers: { 'Cookie': `__session=${session}` } | |
| }); | |
| return dashboard.data.token; | |
| } | |
| module.exports = { authenticateMPG }; | |
| if (require.main === module) { | |
| const email = 'your_email'; | |
| const password = 'your_password'; | |
| authenticateMPG(email, password) | |
| .then(token => console.log('Token:', token)) | |
| .catch(err => console.error('Error:', err.message)); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment