Dat $_SESSION['valid'] lijkt mij volledig overbodig? Controleer simpelweg op het bestaan van een username?
Waarom werk je met $error = '' en $error = 0? Gebruik een omschrijvende naam en/of gebruik iig een Boolse waarde (true of false), dan hoef je ook niet met !=[color=#ff0000]=[/color] 0 te stunten, wat zonder die typecheck ook nogal gevaarlijk is want 0 en '' zijn equivalent als je simpelweg met == (of !=) vergelijkt, op die manier is een fout heel snel gemaakt, bij een Boolean is de kans op dit soort fouten min of meer afwezig...
Ook wil je misschien niet controleren of iets fout gaat, maar of iets goed gaat.
Dan zou je dus kunnen beginnen met $loginOk = false; en alleen als de gebruikersnaam bestaat en de wachtwoorden overeenkomen zet je $loginOk op true. Dit lijkt mij een stuk logischer dan er vanuit gaan dat de login goed is, en alleen als er dingen niet kloppen vervolgens toch maar concluderen dat de login niet goed was, wat je nu in feite doet; dit lijkt mij de omgekeerde wereld, en wederom heel erg gevaarlijk.
Tevens heeft je sessie geen enkele extra controles, bijvoorbeeld whitelisting van IP's of wat dan ook, dus als er ook maar iets in de rest van de code misgaat of iemand op enigerlei wijze je sessie-id kan ontvreemden dan kunnen zij je sessie overnemen en zijn ze binnen?
Ook zou het handig zijn om na een succesvolle inlog je sessieID aan te passen met session_regenerate_id().
Zo voorkom je dat je sessie hetzelfde blijft en opeens overgenomen kan worden. De 'session fixation exploit'
Dit hangt ook af van het gebruik, als je een verbinding hebt waarbij het IP on-the-fly kan veranderen heb je niet zoveel aan bovenstaande aanpak, dan kun je wellicht beter iets anders gebruiken.
Blijkbaar is een user agent "redelijk" uniek. Hoe dan ook, je zult op een of andere manier de identificatie van de machine moeten verankeren in je veiligheidschecks. Indien dit kenmerk op een of andere manier verandert tijdens gebruik zou je iemand direct moeten uitloggen omdat je in zekere zin de ingelogde gebruiker niet meer goed kunt identificeren, je weet simpelweg niet langer zeker of je met dezelfde persoon van doen hebt.
Ook wat @Ariën zegt en wellicht is een aanpak met password_hash() en password_verify() ook handig, als je dit ooit nog eens om wil schrijven naar een uitgebreider loginsysteem inclusief database.
Op het moment dat je met authenticatie / het afschermen van pagina's aan de slag gaat is het eigenlijk ook hoog tijd om over de opbouw van de rest van je applicatie na te denken. Dit om er zorg voor te dragen dat deze veilig is en blijft. Als je dus tig losse PHP-bestanden hebt heb je ook tig ingangen in jouw applicatie. De vraag is of dat een goed idee is, of dat je je beter kunt bedienen van een single point of entry.
De vraag is dan ook eigenlijk: waarom een simpel loginscript? Is dit vanwege tijdsdruk, of dat je echt gewoon een simpele backend nodig hebt? Dit is namelijk niet iets waar je zomaar op zou moeten beknibbelen; als je hier bewust bochten aan het afsnijden bent om tijd te besparen krijg je dit later, wanneer je niet goed hebt nagedacht over de architectuur, gewoon keihard terug op je bord. En dan is er al een complete applicatie opgebouwd, dan zou je dus de spreekwoordelijke grondvesten moeten aanpassen terwijl je huis al staat en zul je zorg moeten dragen voor het niet instorten ervan tijdens de renovatie. Je kunt beter van start gaan met een goed plan, in plaats van terloops allerlei innovaties/verbouwingen uit te voeren.
Maar misschien moet je hier gewoon een keer tegenaan lopen :p.
Heb jij al een overwogen om een directory met .htaccess en .htpassword af te schermen, helemaal geen gedoe? En gemakkelijk. Er zijn zelfs generatoren voor. https://www.htaccessredirect.net/ Via de hostingzijde van een site is dit gemakkelijk in te stellen. Voor als je het echt simpel wilt.